
<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>pymatgen.core.surface &#8212; pymatgen 2020.7.3 documentation</title>
    <link rel="stylesheet" href="../../../_static/basic.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script src="../../../_static/jquery.js"></script>
    <script src="../../../_static/underscore.js"></script>
    <script src="../../../_static/doctools.js"></script>
    <script src="../../../_static/language_data.js"></script>
    <script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />
 
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-33990148-1']);
  _gaq.push(['_trackPageview']);
</script>

  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../../index.html">pymatgen 2020.7.3 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="../../pymatgen.html" accesskey="U">pymatgen</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">pymatgen.core.surface</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
          <div class="body" role="main">
            
  <h1>Source code for pymatgen.core.surface</h1><div class="highlight"><pre>
<span></span><span class="c1"># coding: utf-8</span>
<span class="c1"># Copyright (c) Pymatgen Development Team.</span>
<span class="c1"># Distributed under the terms of the MIT License.</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">This module implements representations of slabs and surfaces, as well as</span>
<span class="sd">algorithms for generating them. If you use this module, please consider</span>
<span class="sd">citing the following work::</span>

<span class="sd">    R. Tran, Z. Xu, B. Radhakrishnan, D. Winston, W. Sun, K. A. Persson,</span>
<span class="sd">    S. P. Ong, &quot;Surface Energies of Elemental Crystals&quot;, Scientific Data,</span>
<span class="sd">    2016, 3:160080, doi: 10.1038/sdata.2016.80.</span>

<span class="sd">as well as::</span>

<span class="sd">    Sun, W.; Ceder, G. Efficient creation and convergence of surface slabs,</span>
<span class="sd">    Surface Science, 2013, 617, 53–59, doi:10.1016/j.susc.2013.05.016.</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">reduce</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="kn">import</span> <span class="nn">math</span>
<span class="kn">import</span> <span class="nn">itertools</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="kn">import</span> <span class="nn">copy</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">json</span>

<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="kn">from</span> <span class="nn">scipy.spatial.distance</span> <span class="kn">import</span> <span class="n">squareform</span>
<span class="kn">from</span> <span class="nn">scipy.cluster.hierarchy</span> <span class="kn">import</span> <span class="n">linkage</span><span class="p">,</span> <span class="n">fcluster</span>

<span class="kn">from</span> <span class="nn">monty.fractions</span> <span class="kn">import</span> <span class="n">lcm</span>

<span class="kn">from</span> <span class="nn">pymatgen.core.periodic_table</span> <span class="kn">import</span> <span class="n">get_el_sp</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.structure</span> <span class="kn">import</span> <span class="n">Structure</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.lattice</span> <span class="kn">import</span> <span class="n">Lattice</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.sites</span> <span class="kn">import</span> <span class="n">PeriodicSite</span>

<span class="kn">from</span> <span class="nn">pymatgen.symmetry.analyzer</span> <span class="kn">import</span> <span class="n">SpacegroupAnalyzer</span>
<span class="kn">from</span> <span class="nn">pymatgen.util.coord</span> <span class="kn">import</span> <span class="n">in_coord_list</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.structure_matcher</span> <span class="kn">import</span> <span class="n">StructureMatcher</span>

<span class="n">__author__</span> <span class="o">=</span> <span class="s2">&quot;Richard Tran, Wenhao Sun, Zihan Xu, Shyue Ping Ong&quot;</span>
<span class="n">__copyright__</span> <span class="o">=</span> <span class="s2">&quot;Copyright 2014, The Materials Virtual Lab&quot;</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s2">&quot;0.1&quot;</span>
<span class="n">__maintainer__</span> <span class="o">=</span> <span class="s2">&quot;Shyue Ping Ong&quot;</span>
<span class="n">__email__</span> <span class="o">=</span> <span class="s2">&quot;ongsp@ucsd.edu&quot;</span>
<span class="n">__date__</span> <span class="o">=</span> <span class="s2">&quot;6/10/14&quot;</span>

<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>


<div class="viewcode-block" id="Slab"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab">[docs]</a><span class="k">class</span> <span class="nc">Slab</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Subclass of Structure representing a Slab. Implements additional</span>
<span class="sd">    attributes pertaining to slabs, but the init method does not</span>
<span class="sd">    actually implement any algorithm that creates a slab. This is a</span>
<span class="sd">    DUMMY class who&#39;s init method only holds information about the</span>
<span class="sd">    slab. Also has additional methods that returns other information</span>
<span class="sd">    about a slab such as the surface area, normal, and atom adsorption.</span>

<span class="sd">    Note that all Slabs have the surface normal oriented perpendicular to the a</span>
<span class="sd">    and b lattice vectors. This means the lattice vectors a and b are in the</span>
<span class="sd">    surface plane and the c vector is out of the surface plane (though not</span>
<span class="sd">    necessarily perpendicular to the surface).</span>

<span class="sd">    .. attribute:: miller_index</span>

<span class="sd">        Miller index of plane parallel to surface.</span>

<span class="sd">    .. attribute:: scale_factor</span>

<span class="sd">        Final computed scale factor that brings the parent cell to the</span>
<span class="sd">        surface cell.</span>

<span class="sd">    .. attribute:: shift</span>

<span class="sd">        The shift value in Angstrom that indicates how much this</span>
<span class="sd">        slab has been shifted.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lattice</span><span class="p">,</span> <span class="n">species</span><span class="p">,</span> <span class="n">coords</span><span class="p">,</span> <span class="n">miller_index</span><span class="p">,</span>
                 <span class="n">oriented_unit_cell</span><span class="p">,</span> <span class="n">shift</span><span class="p">,</span> <span class="n">scale_factor</span><span class="p">,</span> <span class="n">reorient_lattice</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                 <span class="n">validate_proximity</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">to_unit_cell</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                 <span class="n">reconstruction</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                 <span class="n">site_properties</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Makes a Slab structure, a structure object with additional information</span>
<span class="sd">        and methods pertaining to slabs.</span>

<span class="sd">        Args:</span>
<span class="sd">            lattice (Lattice/3x3 array): The lattice, either as a</span>
<span class="sd">                :class:`pymatgen.core.lattice.Lattice` or</span>
<span class="sd">                simply as any 2D array. Each row should correspond to a lattice</span>
<span class="sd">                vector. E.g., [[10,0,0], [20,10,0], [0,0,30]] specifies a</span>
<span class="sd">                lattice with lattice vectors [10,0,0], [20,10,0] and [0,0,30].</span>
<span class="sd">            species ([Specie]): Sequence of species on each site. Can take in</span>
<span class="sd">                flexible input, including:</span>

<span class="sd">                i.  A sequence of element / specie specified either as string</span>
<span class="sd">                    symbols, e.g. [&quot;Li&quot;, &quot;Fe2+&quot;, &quot;P&quot;, ...] or atomic numbers,</span>
<span class="sd">                    e.g., (3, 56, ...) or actual Element or Specie objects.</span>

<span class="sd">                ii. List of dict of elements/species and occupancies, e.g.,</span>
<span class="sd">                    [{&quot;Fe&quot; : 0.5, &quot;Mn&quot;:0.5}, ...]. This allows the setup of</span>
<span class="sd">                    disordered structures.</span>
<span class="sd">            coords (Nx3 array): list of fractional/cartesian coordinates of</span>
<span class="sd">                each species.</span>
<span class="sd">            miller_index ([h, k, l]): Miller index of plane parallel to</span>
<span class="sd">                surface. Note that this is referenced to the input structure. If</span>
<span class="sd">                you need this to be based on the conventional cell,</span>
<span class="sd">                you should supply the conventional structure.</span>
<span class="sd">            oriented_unit_cell (Structure): The oriented_unit_cell from which</span>
<span class="sd">                this Slab is created (by scaling in the c-direction).</span>
<span class="sd">            shift (float): The shift in the c-direction applied to get the</span>
<span class="sd">                termination.</span>
<span class="sd">            scale_factor (array): scale_factor Final computed scale factor</span>
<span class="sd">                that brings the parent cell to the surface cell.</span>
<span class="sd">            reorient_lattice (bool): reorients the lattice parameters such that</span>
<span class="sd">                the c direction is the third vector of the lattice matrix</span>
<span class="sd">            validate_proximity (bool): Whether to check if there are sites</span>
<span class="sd">                that are less than 0.01 Ang apart. Defaults to False.</span>
<span class="sd">            reconstruction (str): Type of reconstruction. Defaultst to None if</span>
<span class="sd">                the slab is not reconstructed.</span>
<span class="sd">            coords_are_cartesian (bool): Set to True if you are providing</span>
<span class="sd">                coordinates in cartesian coordinates. Defaults to False.</span>
<span class="sd">            site_properties (dict): Properties associated with the sites as a</span>
<span class="sd">                dict of sequences, e.g., {&quot;magmom&quot;:[5,5,5,5]}. The sequences</span>
<span class="sd">                have to be the same length as the atomic species and</span>
<span class="sd">                fractional_coords. Defaults to None for no properties.</span>
<span class="sd">            energy (float): A value for the energy.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span> <span class="o">=</span> <span class="n">oriented_unit_cell</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">miller_index</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">shift</span> <span class="o">=</span> <span class="n">shift</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reconstruction</span> <span class="o">=</span> <span class="n">reconstruction</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span> <span class="o">=</span> <span class="n">scale_factor</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">energy</span> <span class="o">=</span> <span class="n">energy</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span> <span class="o">=</span> <span class="n">reorient_lattice</span>
        <span class="n">lattice</span> <span class="o">=</span> <span class="n">Lattice</span><span class="o">.</span><span class="n">from_parameters</span><span class="p">(</span><span class="n">lattice</span><span class="o">.</span><span class="n">a</span><span class="p">,</span> <span class="n">lattice</span><span class="o">.</span><span class="n">b</span><span class="p">,</span> <span class="n">lattice</span><span class="o">.</span><span class="n">c</span><span class="p">,</span>
                                          <span class="n">lattice</span><span class="o">.</span><span class="n">alpha</span><span class="p">,</span> <span class="n">lattice</span><span class="o">.</span><span class="n">beta</span><span class="p">,</span>
                                          <span class="n">lattice</span><span class="o">.</span><span class="n">gamma</span><span class="p">)</span> \
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span> <span class="k">else</span> <span class="n">lattice</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span>
            <span class="n">lattice</span><span class="p">,</span> <span class="n">species</span><span class="p">,</span> <span class="n">coords</span><span class="p">,</span> <span class="n">validate_proximity</span><span class="o">=</span><span class="n">validate_proximity</span><span class="p">,</span>
            <span class="n">to_unit_cell</span><span class="o">=</span><span class="n">to_unit_cell</span><span class="p">,</span>
            <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="n">coords_are_cartesian</span><span class="p">,</span>
            <span class="n">site_properties</span><span class="o">=</span><span class="n">site_properties</span><span class="p">)</span>

<div class="viewcode-block" id="Slab.get_orthogonal_c_slab"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.get_orthogonal_c_slab">[docs]</a>    <span class="k">def</span> <span class="nf">get_orthogonal_c_slab</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method returns a Slab where the normal (c lattice vector) is</span>
<span class="sd">        &quot;forced&quot; to be exactly orthogonal to the surface a and b lattice</span>
<span class="sd">        vectors. **Note that this breaks inherent symmetries in the slab.**</span>
<span class="sd">        It should be pointed out that orthogonality is not required to get good</span>
<span class="sd">        surface energies, but it can be useful in cases where the slabs are</span>
<span class="sd">        subsequently used for postprocessing of some kind, e.g. generating</span>
<span class="sd">        GBs or interfaces.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span>
        <span class="n">new_c</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
        <span class="n">new_c</span> <span class="o">/=</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">new_c</span><span class="p">)</span>
        <span class="n">new_c</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">new_c</span><span class="p">)</span> <span class="o">*</span> <span class="n">new_c</span>
        <span class="n">new_latt</span> <span class="o">=</span> <span class="n">Lattice</span><span class="p">([</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">new_c</span><span class="p">])</span>
        <span class="k">return</span> <span class="n">Slab</span><span class="p">(</span><span class="n">lattice</span><span class="o">=</span><span class="n">new_latt</span><span class="p">,</span> <span class="n">species</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">species_and_occu</span><span class="p">,</span>
                    <span class="n">coords</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">cart_coords</span><span class="p">,</span> <span class="n">miller_index</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span>
                    <span class="n">oriented_unit_cell</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">,</span>
                    <span class="n">shift</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span> <span class="n">scale_factor</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span><span class="p">,</span>
                    <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">energy</span><span class="p">,</span>
                    <span class="n">reorient_lattice</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span><span class="p">,</span>
                    <span class="n">site_properties</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">site_properties</span><span class="p">)</span></div>

<div class="viewcode-block" id="Slab.get_tasker2_slabs"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.get_tasker2_slabs">[docs]</a>    <span class="k">def</span> <span class="nf">get_tasker2_slabs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">0.01</span><span class="p">,</span> <span class="n">same_species_only</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get a list of slabs that have been Tasker 2 corrected.</span>

<span class="sd">        Args:</span>
<span class="sd">            tol (float): Tolerance to determine if atoms are within same plane.</span>
<span class="sd">                This is a fractional tolerance, not an absolute one.</span>
<span class="sd">            same_species_only (bool): If True, only that are of the exact same</span>
<span class="sd">                species as the atom at the outermost surface are considered for</span>
<span class="sd">                moving. Otherwise, all atoms regardless of species that is</span>
<span class="sd">                within tol are considered for moving. Default is True (usually</span>
<span class="sd">                the desired behavior).</span>

<span class="sd">        Returns:</span>
<span class="sd">            ([Slab]) List of tasker 2 corrected slabs.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sites</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sites</span><span class="p">)</span>
        <span class="n">slabs</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="n">sortedcsites</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">sites</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">site</span><span class="p">:</span> <span class="n">site</span><span class="o">.</span><span class="n">c</span><span class="p">)</span>

        <span class="c1"># Determine what fraction the slab is of the total cell size in the</span>
        <span class="c1"># c direction. Round to nearest rational number.</span>
        <span class="n">nlayers_total</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">c</span> <span class="o">/</span>
                                  <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">c</span><span class="p">))</span>
        <span class="n">nlayers_slab</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">((</span><span class="n">sortedcsites</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">c</span> <span class="o">-</span> <span class="n">sortedcsites</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">c</span><span class="p">)</span>
                                 <span class="o">*</span> <span class="n">nlayers_total</span><span class="p">))</span>
        <span class="n">slab_ratio</span> <span class="o">=</span> <span class="n">nlayers_slab</span> <span class="o">/</span> <span class="n">nlayers_total</span>

        <span class="n">a</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">symm_structure</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">get_symmetrized_structure</span><span class="p">()</span>

        <span class="k">def</span> <span class="nf">equi_index</span><span class="p">(</span><span class="n">site</span><span class="p">):</span>
            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">equi_sites</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">symm_structure</span><span class="o">.</span><span class="n">equivalent_sites</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">equi_sites</span><span class="p">:</span>
                    <span class="k">return</span> <span class="n">i</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Cannot determine equi index!&quot;</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">surface_site</span><span class="p">,</span> <span class="n">shift</span> <span class="ow">in</span> <span class="p">[(</span><span class="n">sortedcsites</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">slab_ratio</span><span class="p">),</span>
                                    <span class="p">(</span><span class="n">sortedcsites</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="o">-</span><span class="n">slab_ratio</span><span class="p">)]:</span>
            <span class="n">tomove</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="n">fixed</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">sites</span><span class="p">:</span>
                <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">c</span> <span class="o">-</span> <span class="n">surface_site</span><span class="o">.</span><span class="n">c</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">tol</span> <span class="ow">and</span> <span class="p">(</span>
                        <span class="p">(</span><span class="ow">not</span> <span class="n">same_species_only</span><span class="p">)</span> <span class="ow">or</span>
                        <span class="n">site</span><span class="o">.</span><span class="n">species</span> <span class="o">==</span> <span class="n">surface_site</span><span class="o">.</span><span class="n">species</span><span class="p">):</span>
                    <span class="n">tomove</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">site</span><span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">fixed</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">site</span><span class="p">)</span>

            <span class="c1"># Sort and group the sites by the species and symmetry equivalence</span>
            <span class="n">tomove</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">tomove</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">equi_index</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>

            <span class="n">grouped</span> <span class="o">=</span> <span class="p">[</span><span class="nb">list</span><span class="p">(</span><span class="n">sites</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">sites</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">groupby</span><span class="p">(</span>
                <span class="n">tomove</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">equi_index</span><span class="p">(</span><span class="n">s</span><span class="p">))]</span>

            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">tomove</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="nb">any</span><span class="p">([</span><span class="nb">len</span><span class="p">(</span><span class="n">g</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">grouped</span><span class="p">]):</span>
                <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">&quot;Odd number of sites to divide! Try changing &quot;</span>
                              <span class="s2">&quot;the tolerance to ensure even division of &quot;</span>
                              <span class="s2">&quot;sites or create supercells in a or b directions &quot;</span>
                              <span class="s2">&quot;to allow for atoms to be moved!&quot;</span><span class="p">)</span>
                <span class="k">continue</span>
            <span class="n">combinations</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">grouped</span><span class="p">:</span>
                <span class="n">combinations</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
                    <span class="p">[</span><span class="n">c</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">combinations</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">g</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">))])</span>

            <span class="k">for</span> <span class="n">selection</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="o">*</span><span class="n">combinations</span><span class="p">):</span>
                <span class="n">species</span> <span class="o">=</span> <span class="p">[</span><span class="n">site</span><span class="o">.</span><span class="n">species</span> <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">fixed</span><span class="p">]</span>
                <span class="n">fcoords</span> <span class="o">=</span> <span class="p">[</span><span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span> <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">fixed</span><span class="p">]</span>

                <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">tomove</span><span class="p">:</span>
                    <span class="n">species</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">species</span><span class="p">)</span>
                    <span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">selection</span><span class="p">:</span>
                        <span class="k">if</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">group</span><span class="p">:</span>
                            <span class="n">fcoords</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">)</span>
                            <span class="k">break</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="c1"># Move unselected atom to the opposite surface.</span>
                        <span class="n">fcoords</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">frac_coords</span> <span class="o">+</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">shift</span><span class="p">])</span>

                <span class="c1"># sort by species to put all similar species together.</span>
                <span class="n">sp_fcoord</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">species</span><span class="p">,</span> <span class="n">fcoords</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
                <span class="n">species</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sp_fcoord</span><span class="p">]</span>
                <span class="n">fcoords</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sp_fcoord</span><span class="p">]</span>
                <span class="n">slab</span> <span class="o">=</span> <span class="n">Slab</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="p">,</span> <span class="n">species</span><span class="p">,</span> <span class="n">fcoords</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span>
                            <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span>
                            <span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">energy</span><span class="p">,</span>
                            <span class="n">reorient_lattice</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span><span class="p">)</span>
                <span class="n">slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>
        <span class="n">s</span> <span class="o">=</span> <span class="n">StructureMatcher</span><span class="p">()</span>
        <span class="n">unique</span> <span class="o">=</span> <span class="p">[</span><span class="n">ss</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">ss</span> <span class="ow">in</span> <span class="n">s</span><span class="o">.</span><span class="n">group_structures</span><span class="p">(</span><span class="n">slabs</span><span class="p">)]</span>
        <span class="k">return</span> <span class="n">unique</span></div>

<div class="viewcode-block" id="Slab.is_symmetric"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.is_symmetric">[docs]</a>    <span class="k">def</span> <span class="nf">is_symmetric</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symprec</span><span class="o">=</span><span class="mf">0.1</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Checks if slab is symmetric, i.e., contains inversion symmetry.</span>

<span class="sd">        Args:</span>
<span class="sd">            symprec (float): Symmetry precision used for SpaceGroup analyzer.</span>

<span class="sd">        Returns:</span>
<span class="sd">            (bool) Whether slab contains inversion symmetry.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symprec</span><span class="o">=</span><span class="n">symprec</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">sg</span><span class="o">.</span><span class="n">is_laue</span><span class="p">()</span></div>

<div class="viewcode-block" id="Slab.get_sorted_structure"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.get_sorted_structure">[docs]</a>    <span class="k">def</span> <span class="nf">get_sorted_structure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Get a sorted copy of the structure. The parameters have the same</span>
<span class="sd">        meaning as in list.sort. By default, sites are sorted by the</span>
<span class="sd">        electronegativity of the species. Note that Slab has to override this</span>
<span class="sd">        because of the different __init__ args.</span>

<span class="sd">        Args:</span>
<span class="sd">            key: Specifies a function of one argument that is used to extract</span>
<span class="sd">                a comparison key from each list element: key=str.lower. The</span>
<span class="sd">                default value is None (compare the elements directly).</span>
<span class="sd">            reverse (bool): If set to True, then the list elements are sorted</span>
<span class="sd">                as if each comparison were reversed.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sites</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span> <span class="n">reverse</span><span class="o">=</span><span class="n">reverse</span><span class="p">)</span>
        <span class="n">s</span> <span class="o">=</span> <span class="n">Structure</span><span class="o">.</span><span class="n">from_sites</span><span class="p">(</span><span class="n">sites</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">Slab</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">lattice</span><span class="p">,</span> <span class="n">s</span><span class="o">.</span><span class="n">species_and_occu</span><span class="p">,</span> <span class="n">s</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span><span class="p">,</span> <span class="n">site_properties</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="n">site_properties</span><span class="p">,</span>
                    <span class="n">reorient_lattice</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span><span class="p">)</span></div>

<div class="viewcode-block" id="Slab.copy"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.copy">[docs]</a>    <span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">site_properties</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sanitize</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Convenience method to get a copy of the structure, with options to add</span>
<span class="sd">        site properties.</span>

<span class="sd">        Args:</span>
<span class="sd">            site_properties (dict): Properties to add or override. The</span>
<span class="sd">                properties are specified in the same way as the constructor,</span>
<span class="sd">                i.e., as a dict of the form {property: [values]}. The</span>
<span class="sd">                properties should be in the order of the *original* structure</span>
<span class="sd">                if you are performing sanitization.</span>
<span class="sd">            sanitize (bool): If True, this method will return a sanitized</span>
<span class="sd">                structure. Sanitization performs a few things: (i) The sites are</span>
<span class="sd">                sorted by electronegativity, (ii) a LLL lattice reduction is</span>
<span class="sd">                carried out to obtain a relatively orthogonalized cell,</span>
<span class="sd">                (iii) all fractional coords for sites are mapped into the</span>
<span class="sd">                unit cell.</span>

<span class="sd">        Returns:</span>
<span class="sd">            A copy of the Structure, with optionally new site_properties and</span>
<span class="sd">            optionally sanitized.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">props</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">site_properties</span>
        <span class="k">if</span> <span class="n">site_properties</span><span class="p">:</span>
            <span class="n">props</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">site_properties</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">Slab</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">species_and_occu</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span><span class="p">,</span> <span class="n">site_properties</span><span class="o">=</span><span class="n">props</span><span class="p">,</span>
                    <span class="n">reorient_lattice</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span><span class="p">)</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">dipole</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculates the dipole of the Slab in the direction of the surface</span>
<span class="sd">        normal. Note that the Slab must be oxidation state-decorated for this</span>
<span class="sd">        to work properly. Otherwise, the Slab will always have a dipole of 0.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">dipole</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
        <span class="n">mid_pt</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cart_coords</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">normal</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">normal</span>
        <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span>
            <span class="n">charge</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="nb">getattr</span><span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="s2">&quot;oxi_state&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">*</span> <span class="n">amt</span>
                          <span class="k">for</span> <span class="n">sp</span><span class="p">,</span> <span class="n">amt</span> <span class="ow">in</span> <span class="n">site</span><span class="o">.</span><span class="n">species</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span>
            <span class="n">dipole</span> <span class="o">+=</span> <span class="n">charge</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">coords</span> <span class="o">-</span> <span class="n">mid_pt</span><span class="p">,</span> <span class="n">normal</span><span class="p">)</span> <span class="o">*</span> <span class="n">normal</span>
        <span class="k">return</span> <span class="n">dipole</span>

<div class="viewcode-block" id="Slab.is_polar"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.is_polar">[docs]</a>    <span class="k">def</span> <span class="nf">is_polar</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol_dipole_per_unit_area</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Checks whether the surface is polar by computing the dipole per unit</span>
<span class="sd">        area. Note that the Slab must be oxidation state-decorated for this</span>
<span class="sd">        to work properly. Otherwise, the Slab will always be non-polar.</span>

<span class="sd">        Args:</span>
<span class="sd">            tol_dipole_per_unit_area (float): A tolerance. If the dipole</span>
<span class="sd">                magnitude per unit area is less than this value, the Slab is</span>
<span class="sd">                considered non-polar. Defaults to 1e-3, which is usually</span>
<span class="sd">                pretty good. Normalized dipole per unit area is used as it is</span>
<span class="sd">                more reliable than using the total, which tends to be larger for</span>
<span class="sd">                slabs with larger surface areas.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">dip_per_unit_area</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dipole</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">surface_area</span>
        <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">dip_per_unit_area</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">tol_dipole_per_unit_area</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">normal</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculates the surface normal vector of the slab</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">normal</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">normal</span> <span class="o">/=</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">normal</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">normal</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">surface_area</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculates the surface area of the slab</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">m</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span>
        <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">cross</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">center_of_mass</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculates the center of mass of the slab</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">weights</span> <span class="o">=</span> <span class="p">[</span><span class="n">s</span><span class="o">.</span><span class="n">species</span><span class="o">.</span><span class="n">weight</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">]</span>
        <span class="n">center_of_mass</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">average</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span>
                                    <span class="n">weights</span><span class="o">=</span><span class="n">weights</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">center_of_mass</span>

<div class="viewcode-block" id="Slab.add_adsorbate_atom"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.add_adsorbate_atom">[docs]</a>    <span class="k">def</span> <span class="nf">add_adsorbate_atom</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">indices</span><span class="p">,</span> <span class="n">specie</span><span class="p">,</span> <span class="n">distance</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Gets the structure of single atom adsorption.</span>
<span class="sd">        slab structure from the Slab class(in [0, 0, 1])</span>

<span class="sd">        Args:</span>
<span class="sd">            indices ([int]): Indices of sites on which to put the absorbate.</span>
<span class="sd">                Absorbed atom will be displaced relative to the center of</span>
<span class="sd">                these sites.</span>
<span class="sd">            specie (Specie/Element/str): adsorbed atom species</span>
<span class="sd">            distance (float): between centers of the adsorbed atom and the</span>
<span class="sd">                given site in Angstroms.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># Let&#39;s do the work in cartesian coords</span>
        <span class="n">center</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sum</span><span class="p">([</span><span class="bp">self</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">coords</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">indices</span><span class="p">],</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span>
            <span class="n">indices</span><span class="p">)</span>

        <span class="n">coords</span> <span class="o">=</span> <span class="n">center</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">normal</span> <span class="o">*</span> <span class="n">distance</span> <span class="o">/</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">normal</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">specie</span><span class="p">,</span> <span class="n">coords</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">comp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">composition</span>
        <span class="n">outs</span> <span class="o">=</span> <span class="p">[</span>
            <span class="s2">&quot;Slab Summary (</span><span class="si">%s</span><span class="s2">)&quot;</span> <span class="o">%</span> <span class="n">comp</span><span class="o">.</span><span class="n">formula</span><span class="p">,</span>
            <span class="s2">&quot;Reduced Formula: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">comp</span><span class="o">.</span><span class="n">reduced_formula</span><span class="p">,</span>
            <span class="s2">&quot;Miller index: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,),</span>
            <span class="s2">&quot;Shift: </span><span class="si">%.4f</span><span class="s2">, Scale Factor: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span>
                                               <span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span><span class="o">.</span><span class="fm">__str__</span><span class="p">())]</span>

        <span class="k">def</span> <span class="nf">to_s</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
            <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%0.6f</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">x</span>
        <span class="n">outs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;abc   : &quot;</span> <span class="o">+</span> <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">to_s</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="o">.</span><span class="n">rjust</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
                                           <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">abc</span><span class="p">]))</span>
        <span class="n">outs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;angles: &quot;</span> <span class="o">+</span> <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">to_s</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="o">.</span><span class="n">rjust</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
                                           <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">angles</span><span class="p">]))</span>
        <span class="n">outs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;Sites (</span><span class="si">{i}</span><span class="s2">)&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">)))</span>
        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
            <span class="n">outs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="n">site</span><span class="o">.</span><span class="n">species_string</span><span class="p">,</span>
                                  <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">to_s</span><span class="p">(</span><span class="n">j</span><span class="p">)</span><span class="o">.</span><span class="n">rjust</span><span class="p">(</span><span class="mi">12</span><span class="p">)</span>
                                            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">])]))</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">outs</span><span class="p">)</span>

<div class="viewcode-block" id="Slab.as_dict"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.as_dict">[docs]</a>    <span class="k">def</span> <span class="nf">as_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: MSONAble dict</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">d</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">as_dict</span><span class="p">()</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;@module&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__module__</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;@class&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;oriented_unit_cell&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">as_dict</span><span class="p">()</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;miller_index&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;shift&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">shift</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;scale_factor&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">scale_factor</span><span class="o">.</span><span class="n">tolist</span><span class="p">()</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;reconstruction&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">reconstruction</span>
        <span class="n">d</span><span class="p">[</span><span class="s2">&quot;energy&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">energy</span>
        <span class="k">return</span> <span class="n">d</span></div>

<div class="viewcode-block" id="Slab.from_dict"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.from_dict">[docs]</a>    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">from_dict</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param d: dict</span>
<span class="sd">        :return: Creates slab from dict.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">lattice</span> <span class="o">=</span> <span class="n">Lattice</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;lattice&quot;</span><span class="p">])</span>
        <span class="n">sites</span> <span class="o">=</span> <span class="p">[</span><span class="n">PeriodicSite</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">sd</span><span class="p">,</span> <span class="n">lattice</span><span class="p">)</span> <span class="k">for</span> <span class="n">sd</span> <span class="ow">in</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;sites&quot;</span><span class="p">]]</span>
        <span class="n">s</span> <span class="o">=</span> <span class="n">Structure</span><span class="o">.</span><span class="n">from_sites</span><span class="p">(</span><span class="n">sites</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">Slab</span><span class="p">(</span>
            <span class="n">lattice</span><span class="o">=</span><span class="n">lattice</span><span class="p">,</span>
            <span class="n">species</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="n">species_and_occu</span><span class="p">,</span> <span class="n">coords</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span>
            <span class="n">miller_index</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;miller_index&quot;</span><span class="p">],</span>
            <span class="n">oriented_unit_cell</span><span class="o">=</span><span class="n">Structure</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;oriented_unit_cell&quot;</span><span class="p">]),</span>
            <span class="n">shift</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;shift&quot;</span><span class="p">],</span> <span class="n">scale_factor</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;scale_factor&quot;</span><span class="p">],</span>
            <span class="n">site_properties</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="n">site_properties</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;energy&quot;</span><span class="p">]</span>
        <span class="p">)</span></div>

<div class="viewcode-block" id="Slab.get_surface_sites"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.get_surface_sites">[docs]</a>    <span class="k">def</span> <span class="nf">get_surface_sites</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tag</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns the surface sites and their indices in a dictionary. The</span>
<span class="sd">        oriented unit cell of the slab will determine the coordination number</span>
<span class="sd">        of a typical site. We use VoronoiNN to determine the</span>
<span class="sd">        coordination number of bulk sites and slab sites. Due to the</span>
<span class="sd">        pathological error resulting from some surface sites in the</span>
<span class="sd">        VoronoiNN, we assume any site that has this error is a surface</span>
<span class="sd">        site as well. This will work for elemental systems only for now. Useful</span>
<span class="sd">        for analysis involving broken bonds and for finding adsorption sites.</span>

<span class="sd">            Args:</span>
<span class="sd">                tag (bool): Option to adds site attribute &quot;is_surfsite&quot; (bool)</span>
<span class="sd">                    to all sites of slab. Defaults to False</span>

<span class="sd">            Returns:</span>
<span class="sd">                A dictionary grouping sites on top and bottom of the slab</span>
<span class="sd">                together.</span>
<span class="sd">                {&quot;top&quot;: [sites with indices], &quot;bottom&quot;: [sites with indices}</span>

<span class="sd">        TODO:</span>
<span class="sd">            Is there a way to determine site equivalence between sites in a slab</span>
<span class="sd">            and bulk system? This would allow us get the coordination number of</span>
<span class="sd">            a specific site for multi-elemental systems or systems with more</span>
<span class="sd">            than one unequivalent site. This will allow us to use this for</span>
<span class="sd">            compound systems.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="kn">from</span> <span class="nn">pymatgen.analysis.local_env</span> <span class="kn">import</span> <span class="n">VoronoiNN</span>

        <span class="c1"># Get a dictionary of coordination numbers</span>
        <span class="c1"># for each distinct site in the structure</span>
        <span class="n">a</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">)</span>
        <span class="n">ucell</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">get_symmetrized_structure</span><span class="p">()</span>
        <span class="n">cn_dict</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">v</span> <span class="o">=</span> <span class="n">VoronoiNN</span><span class="p">()</span>
        <span class="n">unique_indices</span> <span class="o">=</span> <span class="p">[</span><span class="n">equ</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">equ</span> <span class="ow">in</span> <span class="n">ucell</span><span class="o">.</span><span class="n">equivalent_indices</span><span class="p">]</span>

        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">unique_indices</span><span class="p">:</span>
            <span class="n">el</span> <span class="o">=</span> <span class="n">ucell</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">species_string</span>
            <span class="k">if</span> <span class="n">el</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cn_dict</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="n">cn_dict</span><span class="p">[</span><span class="n">el</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="c1"># Since this will get the cn as a result of the weighted polyhedra, the</span>
            <span class="c1"># slightest difference in cn will indicate a different environment for a</span>
            <span class="c1"># species, eg. bond distance of each neighbor or neighbor species. The</span>
            <span class="c1"># decimal place to get some cn to be equal.</span>
            <span class="n">cn</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">get_cn</span><span class="p">(</span><span class="n">ucell</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">use_weights</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
            <span class="n">cn</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%.5f</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">cn</span><span class="p">,</span> <span class="mi">5</span><span class="p">)))</span>
            <span class="k">if</span> <span class="n">cn</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cn_dict</span><span class="p">[</span><span class="n">el</span><span class="p">]:</span>
                <span class="n">cn_dict</span><span class="p">[</span><span class="n">el</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cn</span><span class="p">)</span>

        <span class="n">v</span> <span class="o">=</span> <span class="n">VoronoiNN</span><span class="p">()</span>

        <span class="n">surf_sites_dict</span><span class="p">,</span> <span class="n">properties</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;top&quot;</span><span class="p">:</span> <span class="p">[],</span> <span class="s2">&quot;bottom&quot;</span><span class="p">:</span> <span class="p">[]},</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
            <span class="c1"># Determine if site is closer to the top or bottom of the slab</span>
            <span class="n">top</span> <span class="o">=</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_of_mass</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>

            <span class="k">try</span><span class="p">:</span>
                <span class="c1"># A site is a surface site, if its environment does</span>
                <span class="c1"># not fit the environment of other sites</span>
                <span class="n">cn</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%.5f</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">get_cn</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">use_weights</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span> <span class="mi">5</span><span class="p">)))</span>
                <span class="k">if</span> <span class="n">cn</span> <span class="o">&lt;</span> <span class="nb">min</span><span class="p">(</span><span class="n">cn_dict</span><span class="p">[</span><span class="n">site</span><span class="o">.</span><span class="n">species_string</span><span class="p">]):</span>
                    <span class="n">properties</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
                    <span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;top&quot;</span> <span class="k">if</span> <span class="n">top</span> <span class="k">else</span> <span class="s2">&quot;bottom&quot;</span>
                    <span class="n">surf_sites_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="n">site</span><span class="p">,</span> <span class="n">i</span><span class="p">])</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">properties</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
            <span class="k">except</span> <span class="ne">RuntimeError</span><span class="p">:</span>
                <span class="c1"># or if pathological error is returned, indicating a surface site</span>
                <span class="n">properties</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
                <span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;top&quot;</span> <span class="k">if</span> <span class="n">top</span> <span class="k">else</span> <span class="s2">&quot;bottom&quot;</span>
                <span class="n">surf_sites_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="n">site</span><span class="p">,</span> <span class="n">i</span><span class="p">])</span>

        <span class="k">if</span> <span class="n">tag</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">add_site_property</span><span class="p">(</span><span class="s2">&quot;is_surf_site&quot;</span><span class="p">,</span> <span class="n">properties</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">surf_sites_dict</span></div>

<div class="viewcode-block" id="Slab.have_equivalent_surfaces"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.have_equivalent_surfaces">[docs]</a>    <span class="k">def</span> <span class="nf">have_equivalent_surfaces</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Check if we have same number of equivalent sites on both surfaces.</span>
<span class="sd">        This is an alternative to checking Laue symmetry (is_symmetric())</span>
<span class="sd">        if we want to ensure both surfaces in the slab are the same</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># tag the sites as either surface sites or not</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">get_surface_sites</span><span class="p">(</span><span class="n">tag</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

        <span class="n">a</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">symm_structure</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">get_symmetrized_structure</span><span class="p">()</span>

        <span class="c1"># ensure each site on one surface has a</span>
        <span class="c1"># corresponding equivalent site on the other</span>
        <span class="n">equal_surf_sites</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">equ</span> <span class="ow">in</span> <span class="n">symm_structure</span><span class="o">.</span><span class="n">equivalent_sites</span><span class="p">:</span>
            <span class="c1"># Top and bottom are arbitrary, we will just determine</span>
            <span class="c1"># if one site is on one side of the slab or the other</span>
            <span class="n">top</span><span class="p">,</span> <span class="n">bottom</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
            <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">equ</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">is_surf_site</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_of_mass</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span>
                        <span class="n">top</span> <span class="o">+=</span> <span class="mi">1</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">bottom</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="c1"># Check to see if the number of equivalent sites</span>
            <span class="c1"># on one side of the slab are equal to the other</span>
            <span class="n">equal_surf_sites</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">top</span> <span class="o">==</span> <span class="n">bottom</span><span class="p">)</span>

        <span class="k">return</span> <span class="nb">all</span><span class="p">(</span><span class="n">equal_surf_sites</span><span class="p">)</span></div>

<div class="viewcode-block" id="Slab.get_symmetric_site"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.get_symmetric_site">[docs]</a>    <span class="k">def</span> <span class="nf">get_symmetric_site</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">point</span><span class="p">,</span> <span class="n">cartesian</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method uses symmetry operations to find equivalent sites on</span>
<span class="sd">            both sides of the slab. Works mainly for slabs with Laue</span>
<span class="sd">            symmetry. This is useful for retaining the non-polar and</span>
<span class="sd">            symmetric properties of a slab when creating adsorbed</span>
<span class="sd">            structures or symmetric reconstructions.</span>

<span class="sd">        Arg:</span>
<span class="sd">            point: Fractional coordinate.</span>

<span class="sd">        Returns:</span>
<span class="sd">            point: Fractional coordinate. A point equivalent to the</span>
<span class="sd">                parameter point, but on the other side of the slab</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">ops</span> <span class="o">=</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_symmetry_operations</span><span class="p">(</span><span class="n">cartesian</span><span class="o">=</span><span class="n">cartesian</span><span class="p">)</span>

        <span class="c1"># Each operation on a point will return an equivalent point.</span>
        <span class="c1"># We want to find the point on the other side of the slab.</span>
        <span class="k">for</span> <span class="n">op</span> <span class="ow">in</span> <span class="n">ops</span><span class="p">:</span>
            <span class="n">slab</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">site2</span> <span class="o">=</span> <span class="n">op</span><span class="o">.</span><span class="n">operate</span><span class="p">(</span><span class="n">point</span><span class="p">)</span>
            <span class="k">if</span> <span class="s2">&quot;</span><span class="si">%.6f</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">site2</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="o">==</span> <span class="s2">&quot;</span><span class="si">%.6f</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">point</span><span class="p">[</span><span class="mi">2</span><span class="p">]):</span>
                <span class="k">continue</span>

            <span class="c1"># Add dummy site to check the overall structure is symmetric</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;O&quot;</span><span class="p">,</span> <span class="n">point</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="n">cartesian</span><span class="p">)</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;O&quot;</span><span class="p">,</span> <span class="n">site2</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="n">cartesian</span><span class="p">)</span>
            <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">sg</span><span class="o">.</span><span class="n">is_laue</span><span class="p">():</span>
                <span class="k">break</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># If not symmetric, remove the two added</span>
                <span class="c1"># sites and try another symmetry operator</span>
                <span class="n">slab</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">([</span><span class="nb">len</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>
                <span class="n">slab</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">([</span><span class="nb">len</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>

        <span class="k">return</span> <span class="n">site2</span></div>

<div class="viewcode-block" id="Slab.symmetrically_add_atom"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.symmetrically_add_atom">[docs]</a>    <span class="k">def</span> <span class="nf">symmetrically_add_atom</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">specie</span><span class="p">,</span> <span class="n">point</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Class method for adding a site at a specified point in a slab.</span>
<span class="sd">            Will add the corresponding site on the other side of the</span>
<span class="sd">            slab to maintain equivalent surfaces.</span>

<span class="sd">        Arg:</span>
<span class="sd">            specie (str): The specie to add</span>
<span class="sd">            point (coords): The coordinate of the site in the slab to add.</span>
<span class="sd">            coords_are_cartesian (bool): Is the point in cartesian coordinates</span>

<span class="sd">        Returns:</span>
<span class="sd">            (Slab): The modified slab</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># For now just use the species of the</span>
        <span class="c1"># surface atom as the element to add</span>

        <span class="c1"># Get the index of the corresponding site at the bottom</span>
        <span class="n">point2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_symmetric_site</span><span class="p">(</span><span class="n">point</span><span class="p">,</span> <span class="n">cartesian</span><span class="o">=</span><span class="n">coords_are_cartesian</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">specie</span><span class="p">,</span> <span class="n">point</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="n">coords_are_cartesian</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">specie</span><span class="p">,</span> <span class="n">point2</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="n">coords_are_cartesian</span><span class="p">)</span></div>

<div class="viewcode-block" id="Slab.symmetrically_remove_atoms"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.Slab.symmetrically_remove_atoms">[docs]</a>    <span class="k">def</span> <span class="nf">symmetrically_remove_atoms</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">indices</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Class method for removing sites corresponding to a list of indices.</span>
<span class="sd">            Will remove the corresponding site on the other side of the</span>
<span class="sd">            slab to maintain equivalent surfaces.</span>

<span class="sd">        Arg:</span>
<span class="sd">            indices ([indices]): The indices of the sites</span>
<span class="sd">                in the slab to remove.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">slabcopy</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">())</span><span class="o">.</span><span class="n">get_symmetrized_structure</span><span class="p">()</span>
        <span class="n">points</span> <span class="o">=</span> <span class="p">[</span><span class="n">slabcopy</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">indices</span><span class="p">]</span>
        <span class="n">removal_list</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">for</span> <span class="n">pt</span> <span class="ow">in</span> <span class="n">points</span><span class="p">:</span>
            <span class="c1"># Get the index of the original site on top</span>
            <span class="n">cart_point</span> <span class="o">=</span> <span class="n">slabcopy</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_cartesian_coords</span><span class="p">(</span><span class="n">pt</span><span class="p">)</span>
            <span class="n">dist</span> <span class="o">=</span> <span class="p">[</span><span class="n">site</span><span class="o">.</span><span class="n">distance_from_point</span><span class="p">(</span><span class="n">cart_point</span><span class="p">)</span> <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">slabcopy</span><span class="p">]</span>
            <span class="n">site1</span> <span class="o">=</span> <span class="n">dist</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">dist</span><span class="p">))</span>

            <span class="c1"># Get the index of the corresponding site at the bottom</span>
            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">eq_sites</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">slabcopy</span><span class="o">.</span><span class="n">equivalent_sites</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">slabcopy</span><span class="p">[</span><span class="n">site1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">eq_sites</span><span class="p">:</span>
                    <span class="n">eq_indices</span> <span class="o">=</span> <span class="n">slabcopy</span><span class="o">.</span><span class="n">equivalent_indices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                    <span class="k">break</span>
            <span class="n">i1</span> <span class="o">=</span> <span class="n">eq_indices</span><span class="p">[</span><span class="n">eq_sites</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">slabcopy</span><span class="p">[</span><span class="n">site1</span><span class="p">])]</span>

            <span class="k">for</span> <span class="n">i2</span> <span class="ow">in</span> <span class="n">eq_indices</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">i2</span> <span class="o">==</span> <span class="n">i1</span><span class="p">:</span>
                    <span class="k">continue</span>
                <span class="k">if</span> <span class="n">slabcopy</span><span class="p">[</span><span class="n">i2</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">slabcopy</span><span class="p">[</span><span class="n">i1</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span>
                    <span class="k">continue</span>
                <span class="c1"># Test site remove to see if it results in symmetric slab</span>
                <span class="n">s</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
                <span class="n">s</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">([</span><span class="n">i1</span><span class="p">,</span> <span class="n">i2</span><span class="p">])</span>
                <span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">is_symmetric</span><span class="p">():</span>
                    <span class="n">removal_list</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="n">i1</span><span class="p">,</span> <span class="n">i2</span><span class="p">])</span>
                    <span class="k">break</span>

        <span class="c1"># If expected, 2 atoms are removed per index</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">removal_list</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">indices</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">(</span><span class="n">removal_list</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">&quot;Equivalent sites could not be found for removal for all indices. Surface unchanged.&quot;</span><span class="p">)</span></div></div>


<div class="viewcode-block" id="SlabGenerator"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.SlabGenerator">[docs]</a><span class="k">class</span> <span class="nc">SlabGenerator</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This class generates different slabs using shift values determined by where</span>
<span class="sd">    a unique termination can be found along with other criterias such as where a</span>
<span class="sd">    termination doesn&#39;t break a polyhedral bond. The shift value then indicates</span>
<span class="sd">    where the slab layer will begin and terminate in the slab-vacuum system.</span>

<span class="sd">    .. attribute:: oriented_unit_cell</span>

<span class="sd">        A unit cell of the parent structure with the miller</span>
<span class="sd">        index of plane parallel to surface</span>

<span class="sd">    .. attribute:: parent</span>

<span class="sd">        Parent structure from which Slab was derived.</span>

<span class="sd">    .. attribute:: lll_reduce</span>

<span class="sd">        Whether or not the slabs will be orthogonalized</span>

<span class="sd">    .. attribute:: center_slab</span>

<span class="sd">        Whether or not the slabs will be centered between</span>
<span class="sd">        the vacuum layer</span>

<span class="sd">    .. attribute:: slab_scale_factor</span>

<span class="sd">        Final computed scale factor that brings the parent cell to the</span>
<span class="sd">        surface cell.</span>

<span class="sd">    .. attribute:: miller_index</span>

<span class="sd">        Miller index of plane parallel to surface.</span>

<span class="sd">    .. attribute:: min_slab_size</span>

<span class="sd">        Minimum size in angstroms of layers containing atoms</span>

<span class="sd">    .. attribute:: min_vac_size</span>

<span class="sd">        Minimize size in angstroms of layers containing vacuum</span>

<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">initial_structure</span><span class="p">,</span> <span class="n">miller_index</span><span class="p">,</span> <span class="n">min_slab_size</span><span class="p">,</span>
                 <span class="n">min_vacuum_size</span><span class="p">,</span> <span class="n">lll_reduce</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">center_slab</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                 <span class="n">in_unit_planes</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">primitive</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">max_normal_search</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
                 <span class="n">reorient_lattice</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculates the slab scale factor and uses it to generate a unit cell</span>
<span class="sd">        of the initial structure that has been oriented by its miller index.</span>
<span class="sd">        Also stores the initial information needed later on to generate a slab.</span>

<span class="sd">        Args:</span>
<span class="sd">            initial_structure (Structure): Initial input structure. Note that to</span>
<span class="sd">                ensure that the miller indices correspond to usual</span>
<span class="sd">                crystallographic definitions, you should supply a conventional</span>
<span class="sd">                unit cell structure.</span>
<span class="sd">            miller_index ([h, k, l]): Miller index of plane parallel to</span>
<span class="sd">                surface. Note that this is referenced to the input structure. If</span>
<span class="sd">                you need this to be based on the conventional cell,</span>
<span class="sd">                you should supply the conventional structure.</span>
<span class="sd">            min_slab_size (float): In Angstroms or number of hkl planes</span>
<span class="sd">            min_vacuum_size (float): In Angstroms or number of hkl planes</span>
<span class="sd">            lll_reduce (bool): Whether to perform an LLL reduction on the</span>
<span class="sd">                eventual structure.</span>
<span class="sd">            center_slab (bool): Whether to center the slab in the cell with</span>
<span class="sd">                equal vacuum spacing from the top and bottom.</span>
<span class="sd">            in_unit_planes (bool): Whether to set min_slab_size and min_vac_size</span>
<span class="sd">                in units of hkl planes (True) or Angstrom (False/default).</span>
<span class="sd">                Setting in units of planes is useful for ensuring some slabs</span>
<span class="sd">                have a certain nlayer of atoms. e.g. for Cs (100), a 10 Ang</span>
<span class="sd">                slab will result in a slab with only 2 layer of atoms, whereas</span>
<span class="sd">                Fe (100) will have more layer of atoms. By using units of hkl</span>
<span class="sd">                planes instead, we ensure both slabs</span>
<span class="sd">                have the same number of atoms. The slab thickness will be in</span>
<span class="sd">                min_slab_size/math.ceil(self._proj_height/dhkl)</span>
<span class="sd">                multiples of oriented unit cells.</span>
<span class="sd">            primitive (bool): Whether to reduce any generated slabs to a</span>
<span class="sd">                primitive cell (this does **not** mean the slab is generated</span>
<span class="sd">                from a primitive cell, it simply means that after slab</span>
<span class="sd">                generation, we attempt to find shorter lattice vectors,</span>
<span class="sd">                which lead to less surface area and smaller cells).</span>
<span class="sd">            max_normal_search (int): If set to a positive integer, the code will</span>
<span class="sd">                conduct a search for a normal lattice vector that is as</span>
<span class="sd">                perpendicular to the surface as possible by considering</span>
<span class="sd">                multiples linear combinations of lattice vectors up to</span>
<span class="sd">                max_normal_search. This has no bearing on surface energies,</span>
<span class="sd">                but may be useful as a preliminary step to generating slabs</span>
<span class="sd">                for absorption and other sizes. It is typical that this will</span>
<span class="sd">                not be the smallest possible cell for simulation. Normality</span>
<span class="sd">                is not guaranteed, but the oriented cell will have the c</span>
<span class="sd">                vector as normal as possible (within the search range) to the</span>
<span class="sd">                surface. A value of up to the max absolute Miller index is</span>
<span class="sd">                usually sufficient.</span>
<span class="sd">            reorient_lattice (bool): reorients the lattice parameters such that</span>
<span class="sd">                the c direction is the third vector of the lattice matrix</span>

<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># Add Wyckoff symbols of the bulk, will help with</span>
        <span class="c1"># identfying types of sites in the slab system</span>
        <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">initial_structure</span><span class="p">)</span>
        <span class="n">initial_structure</span><span class="o">.</span><span class="n">add_site_property</span><span class="p">(</span><span class="s2">&quot;bulk_wyckoff&quot;</span><span class="p">,</span>
                                            <span class="n">sg</span><span class="o">.</span><span class="n">get_symmetry_dataset</span><span class="p">()[</span><span class="s1">&#39;wyckoffs&#39;</span><span class="p">])</span>
        <span class="n">initial_structure</span><span class="o">.</span><span class="n">add_site_property</span><span class="p">(</span><span class="s2">&quot;bulk_equivalent&quot;</span><span class="p">,</span>
                                            <span class="n">sg</span><span class="o">.</span><span class="n">get_symmetry_dataset</span><span class="p">()[</span><span class="s1">&#39;equivalent_atoms&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">tolist</span><span class="p">())</span>
        <span class="n">latt</span> <span class="o">=</span> <span class="n">initial_structure</span><span class="o">.</span><span class="n">lattice</span>
        <span class="n">miller_index</span> <span class="o">=</span> <span class="n">_reduce_vector</span><span class="p">(</span><span class="n">miller_index</span><span class="p">)</span>
        <span class="c1"># Calculate the surface normal using the reciprocal lattice vector.</span>
        <span class="n">recp</span> <span class="o">=</span> <span class="n">latt</span><span class="o">.</span><span class="n">reciprocal_lattice_crystallographic</span>
        <span class="n">normal</span> <span class="o">=</span> <span class="n">recp</span><span class="o">.</span><span class="n">get_cartesian_coords</span><span class="p">(</span><span class="n">miller_index</span><span class="p">)</span>
        <span class="n">normal</span> <span class="o">/=</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">normal</span><span class="p">)</span>

        <span class="n">slab_scale_factor</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">non_orth_ind</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">eye</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">eye</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">int</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">miller_index</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="c1"># Lattice vector is perpendicular to surface normal, i.e.,</span>
                <span class="c1"># in plane of surface. We will simply choose this lattice</span>
                <span class="c1"># vector as one of the basis vectors.</span>
                <span class="n">slab_scale_factor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">eye</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># Calculate projection of lattice vector onto surface normal.</span>
                <span class="n">d</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">normal</span><span class="p">,</span> <span class="n">latt</span><span class="o">.</span><span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span> <span class="o">/</span> <span class="n">latt</span><span class="o">.</span><span class="n">abc</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                <span class="n">non_orth_ind</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">d</span><span class="p">))</span>

        <span class="c1"># We want the vector that has maximum magnitude in the</span>
        <span class="c1"># direction of the surface normal as the c-direction.</span>
        <span class="c1"># Results in a more &quot;orthogonal&quot; unit cell.</span>
        <span class="n">c_index</span><span class="p">,</span> <span class="n">dist</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">non_orth_ind</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">t</span><span class="p">:</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">non_orth_ind</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">lcm_miller</span> <span class="o">=</span> <span class="n">lcm</span><span class="p">(</span><span class="o">*</span><span class="p">[</span><span class="n">miller_index</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">non_orth_ind</span><span class="p">])</span>
            <span class="k">for</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">di</span><span class="p">),</span> <span class="p">(</span><span class="n">j</span><span class="p">,</span> <span class="n">dj</span><span class="p">)</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">combinations</span><span class="p">(</span><span class="n">non_orth_ind</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
                <span class="n">l</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
                <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">lcm_miller</span> <span class="o">/</span> <span class="n">miller_index</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
                <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">lcm_miller</span> <span class="o">/</span> <span class="n">miller_index</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>
                <span class="n">slab_scale_factor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
                <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">slab_scale_factor</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
                    <span class="k">break</span>

        <span class="k">if</span> <span class="n">max_normal_search</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">slab_scale_factor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">eye</span><span class="p">[</span><span class="n">c_index</span><span class="p">])</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">index_range</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span>
                <span class="nb">reversed</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="n">max_normal_search</span><span class="p">,</span> <span class="n">max_normal_search</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)),</span>
                <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
            <span class="n">candidates</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="k">for</span> <span class="n">uvw</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="n">index_range</span><span class="p">,</span> <span class="n">index_range</span><span class="p">,</span> <span class="n">index_range</span><span class="p">):</span>
                <span class="k">if</span> <span class="p">(</span><span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">uvw</span><span class="p">))</span> <span class="ow">or</span> <span class="nb">abs</span><span class="p">(</span>
                        <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">det</span><span class="p">(</span><span class="n">slab_scale_factor</span> <span class="o">+</span> <span class="p">[</span><span class="n">uvw</span><span class="p">]))</span> <span class="o">&lt;</span> <span class="mf">1e-8</span><span class="p">:</span>
                    <span class="k">continue</span>
                <span class="n">vec</span> <span class="o">=</span> <span class="n">latt</span><span class="o">.</span><span class="n">get_cartesian_coords</span><span class="p">(</span><span class="n">uvw</span><span class="p">)</span>
                <span class="n">l</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">vec</span><span class="p">)</span>
                <span class="n">cosine</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">vec</span><span class="p">,</span> <span class="n">normal</span><span class="p">)</span> <span class="o">/</span> <span class="n">l</span><span class="p">)</span>
                <span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">uvw</span><span class="p">,</span> <span class="n">cosine</span><span class="p">,</span> <span class="n">l</span><span class="p">))</span>
                <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">cosine</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mf">1e-8</span><span class="p">:</span>
                    <span class="c1"># If cosine of 1 is found, no need to search further.</span>
                    <span class="k">break</span>
            <span class="c1"># We want the indices with the maximum absolute cosine,</span>
            <span class="c1"># but smallest possible length.</span>
            <span class="n">uvw</span><span class="p">,</span> <span class="n">cosine</span><span class="p">,</span> <span class="n">l</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">candidates</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="o">-</span><span class="n">x</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span>
            <span class="n">slab_scale_factor</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">uvw</span><span class="p">)</span>

        <span class="n">slab_scale_factor</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">slab_scale_factor</span><span class="p">)</span>

        <span class="c1"># Let&#39;s make sure we have a left-handed crystallographic system</span>
        <span class="k">if</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">det</span><span class="p">(</span><span class="n">slab_scale_factor</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">slab_scale_factor</span> <span class="o">*=</span> <span class="o">-</span><span class="mi">1</span>

        <span class="c1"># Make sure the slab_scale_factor is reduced to avoid</span>
        <span class="c1"># unnecessarily large slabs</span>

        <span class="n">reduced_scale_factor</span> <span class="o">=</span> <span class="p">[</span><span class="n">_reduce_vector</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">slab_scale_factor</span><span class="p">]</span>
        <span class="n">slab_scale_factor</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">reduced_scale_factor</span><span class="p">)</span>

        <span class="n">single</span> <span class="o">=</span> <span class="n">initial_structure</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="n">single</span><span class="o">.</span><span class="n">make_supercell</span><span class="p">(</span><span class="n">slab_scale_factor</span><span class="p">)</span>

        <span class="c1"># When getting the OUC, lets return the most reduced</span>
        <span class="c1"># structure as possible to reduce calculations</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span> <span class="o">=</span> <span class="n">Structure</span><span class="o">.</span><span class="n">from_sites</span><span class="p">(</span><span class="n">single</span><span class="p">,</span>
                                                       <span class="n">to_unit_cell</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_normal_search</span> <span class="o">=</span> <span class="n">max_normal_search</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">parent</span> <span class="o">=</span> <span class="n">initial_structure</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">lll_reduce</span> <span class="o">=</span> <span class="n">lll_reduce</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">center_slab</span> <span class="o">=</span> <span class="n">center_slab</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">slab_scale_factor</span> <span class="o">=</span> <span class="n">slab_scale_factor</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span> <span class="o">=</span> <span class="n">miller_index</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_vac_size</span> <span class="o">=</span> <span class="n">min_vacuum_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span> <span class="o">=</span> <span class="n">min_slab_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">in_unit_planes</span> <span class="o">=</span> <span class="n">in_unit_planes</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">primitive</span> <span class="o">=</span> <span class="n">primitive</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_normal</span> <span class="o">=</span> <span class="n">normal</span>
        <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_proj_height</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">normal</span><span class="p">,</span> <span class="n">c</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span> <span class="o">=</span> <span class="n">reorient_lattice</span>

<div class="viewcode-block" id="SlabGenerator.get_slab"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.SlabGenerator.get_slab">[docs]</a>    <span class="k">def</span> <span class="nf">get_slab</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shift</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method takes in shift value for the c lattice direction and</span>
<span class="sd">        generates a slab based on the given shift. You should rarely use this</span>
<span class="sd">        method. Instead, it is used by other generation algorithms to obtain</span>
<span class="sd">        all slabs.</span>

<span class="sd">        Arg:</span>
<span class="sd">            shift (float): A shift value in Angstrom that determines how much a</span>
<span class="sd">                slab should be shifted.</span>
<span class="sd">            tol (float): Tolerance to determine primitive cell.</span>
<span class="sd">            energy (float): An energy to assign to the slab.</span>

<span class="sd">        Returns:</span>
<span class="sd">            (Slab) A Slab object with a particular shifted oriented unit cell.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">h</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_proj_height</span>
        <span class="n">p</span> <span class="o">=</span> <span class="nb">round</span><span class="p">(</span><span class="n">h</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">d_hkl</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">),</span> <span class="mi">8</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">in_unit_planes</span><span class="p">:</span>
            <span class="n">nlayers_slab</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span> <span class="o">/</span> <span class="n">p</span><span class="p">))</span>
            <span class="n">nlayers_vac</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_vac_size</span> <span class="o">/</span> <span class="n">p</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">nlayers_slab</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span> <span class="o">/</span> <span class="n">h</span><span class="p">))</span>
            <span class="n">nlayers_vac</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_vac_size</span> <span class="o">/</span> <span class="n">h</span><span class="p">))</span>
        <span class="n">nlayers</span> <span class="o">=</span> <span class="n">nlayers_slab</span> <span class="o">+</span> <span class="n">nlayers_vac</span>

        <span class="n">species</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">species_and_occu</span>
        <span class="n">props</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">site_properties</span>
        <span class="n">props</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span> <span class="o">*</span> <span class="n">nlayers_slab</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">props</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>
        <span class="n">frac_coords</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">frac_coords</span>
        <span class="n">frac_coords</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">frac_coords</span><span class="p">)</span> <span class="o">+</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="n">shift</span><span class="p">])[</span><span class="kc">None</span><span class="p">,</span> <span class="p">:]</span>
        <span class="n">frac_coords</span> <span class="o">-=</span> <span class="n">np</span><span class="o">.</span><span class="n">floor</span><span class="p">(</span><span class="n">frac_coords</span><span class="p">)</span>
        <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span>
        <span class="n">new_lattice</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">nlayers</span> <span class="o">*</span> <span class="n">c</span><span class="p">]</span>
        <span class="n">frac_coords</span><span class="p">[:,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">frac_coords</span><span class="p">[:,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">/</span> <span class="n">nlayers</span>
        <span class="n">all_coords</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nlayers_slab</span><span class="p">):</span>
            <span class="n">fcoords</span> <span class="o">=</span> <span class="n">frac_coords</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">fcoords</span><span class="p">[:,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">/</span> <span class="n">nlayers</span>
            <span class="n">all_coords</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">fcoords</span><span class="p">)</span>

        <span class="n">slab</span> <span class="o">=</span> <span class="n">Structure</span><span class="p">(</span><span class="n">new_lattice</span><span class="p">,</span> <span class="n">species</span> <span class="o">*</span> <span class="n">nlayers_slab</span><span class="p">,</span> <span class="n">all_coords</span><span class="p">,</span>
                         <span class="n">site_properties</span><span class="o">=</span><span class="n">props</span><span class="p">)</span>

        <span class="n">scale_factor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">slab_scale_factor</span>
        <span class="c1"># Whether or not to orthogonalize the structure</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">lll_reduce</span><span class="p">:</span>
            <span class="n">lll_slab</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">sanitize</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
            <span class="n">mapping</span> <span class="o">=</span> <span class="n">lll_slab</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">find_mapping</span><span class="p">(</span><span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="p">)</span>
            <span class="n">scale_factor</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">mapping</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">scale_factor</span><span class="p">)</span>
            <span class="n">slab</span> <span class="o">=</span> <span class="n">lll_slab</span>

        <span class="c1"># Whether or not to center the slab layer around the vacuum</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">center_slab</span><span class="p">:</span>
            <span class="n">avg_c</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">average</span><span class="p">([</span><span class="n">c</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">slab</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">])</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">translate_sites</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">slab</span><span class="p">))),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.5</span> <span class="o">-</span> <span class="n">avg_c</span><span class="p">])</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">primitive</span><span class="p">:</span>
            <span class="n">prim</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">get_primitive_structure</span><span class="p">(</span><span class="n">tolerance</span><span class="o">=</span><span class="n">tol</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">energy</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                <span class="n">energy</span> <span class="o">=</span> <span class="n">prim</span><span class="o">.</span><span class="n">volume</span> <span class="o">/</span> <span class="n">slab</span><span class="o">.</span><span class="n">volume</span> <span class="o">*</span> <span class="n">energy</span>
            <span class="n">slab</span> <span class="o">=</span> <span class="n">prim</span>

        <span class="c1"># Reorient the lattice to get the correct reduced cell</span>
        <span class="n">ouc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">primitive</span><span class="p">:</span>
            <span class="c1"># find a reduced ouc</span>
            <span class="n">slab_l</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">lattice</span>
            <span class="n">ouc</span> <span class="o">=</span> <span class="n">ouc</span><span class="o">.</span><span class="n">get_primitive_structure</span><span class="p">(</span><span class="n">constrain_latt</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;a&quot;</span><span class="p">:</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">a</span><span class="p">,</span> <span class="s2">&quot;b&quot;</span><span class="p">:</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">b</span><span class="p">,</span>
                                                              <span class="s2">&quot;alpha&quot;</span><span class="p">:</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">alpha</span><span class="p">,</span>
                                                              <span class="s2">&quot;beta&quot;</span><span class="p">:</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">beta</span><span class="p">,</span>
                                                              <span class="s2">&quot;gamma&quot;</span><span class="p">:</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">gamma</span><span class="p">})</span>
            <span class="c1"># Check this is the correct oriented unit cell</span>
            <span class="n">ouc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span> <span class="k">if</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">a</span> <span class="o">!=</span> <span class="n">ouc</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">a</span> <span class="ow">or</span> <span class="n">slab_l</span><span class="o">.</span><span class="n">b</span> <span class="o">!=</span> <span class="n">ouc</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">b</span> <span class="k">else</span> <span class="n">ouc</span>

        <span class="k">return</span> <span class="n">Slab</span><span class="p">(</span><span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="p">,</span> <span class="n">slab</span><span class="o">.</span><span class="n">species_and_occu</span><span class="p">,</span>
                    <span class="n">slab</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span>
                    <span class="n">ouc</span><span class="p">,</span> <span class="n">shift</span><span class="p">,</span> <span class="n">scale_factor</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="n">energy</span><span class="p">,</span>
                    <span class="n">site_properties</span><span class="o">=</span><span class="n">slab</span><span class="o">.</span><span class="n">site_properties</span><span class="p">,</span>
                    <span class="n">reorient_lattice</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reorient_lattice</span><span class="p">)</span></div>

    <span class="k">def</span> <span class="nf">_calculate_possible_shifts</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">):</span>
        <span class="n">frac_coords</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">frac_coords</span>
        <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">frac_coords</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="c1"># Clustering does not work when there is only one data point.</span>
            <span class="n">shift</span> <span class="o">=</span> <span class="n">frac_coords</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.5</span>
            <span class="k">return</span> <span class="p">[</span><span class="n">shift</span> <span class="o">-</span> <span class="n">math</span><span class="o">.</span><span class="n">floor</span><span class="p">(</span><span class="n">shift</span><span class="p">)]</span>

        <span class="c1"># We cluster the sites according to the c coordinates. But we need to</span>
        <span class="c1"># take into account PBC. Let&#39;s compute a fractional c-coordinate</span>
        <span class="c1"># distance matrix that accounts for PBC.</span>
        <span class="n">dist_matrix</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="p">))</span>
        <span class="n">h</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_proj_height</span>
        <span class="c1"># Projection of c lattice vector in</span>
        <span class="c1"># direction of surface normal.</span>
        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">combinations</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)),</span> <span class="mi">2</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">j</span><span class="p">:</span>
                <span class="n">cdist</span> <span class="o">=</span> <span class="n">frac_coords</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">frac_coords</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span>
                <span class="n">cdist</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">cdist</span> <span class="o">-</span> <span class="nb">round</span><span class="p">(</span><span class="n">cdist</span><span class="p">))</span> <span class="o">*</span> <span class="n">h</span>
                <span class="n">dist_matrix</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">cdist</span>
                <span class="n">dist_matrix</span><span class="p">[</span><span class="n">j</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">cdist</span>

        <span class="n">condensed_m</span> <span class="o">=</span> <span class="n">squareform</span><span class="p">(</span><span class="n">dist_matrix</span><span class="p">)</span>
        <span class="n">z</span> <span class="o">=</span> <span class="n">linkage</span><span class="p">(</span><span class="n">condensed_m</span><span class="p">)</span>
        <span class="n">clusters</span> <span class="o">=</span> <span class="n">fcluster</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">tol</span><span class="p">,</span> <span class="n">criterion</span><span class="o">=</span><span class="s2">&quot;distance&quot;</span><span class="p">)</span>

        <span class="c1"># Generate dict of cluster# to c val - doesn&#39;t matter what the c is.</span>
        <span class="n">c_loc</span> <span class="o">=</span> <span class="p">{</span><span class="n">c</span><span class="p">:</span> <span class="n">frac_coords</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">clusters</span><span class="p">)}</span>

        <span class="c1"># Put all c into the unit cell.</span>
        <span class="n">possible_c</span> <span class="o">=</span> <span class="p">[</span><span class="n">c</span> <span class="o">-</span> <span class="n">math</span><span class="o">.</span><span class="n">floor</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">c_loc</span><span class="o">.</span><span class="n">values</span><span class="p">())]</span>

        <span class="c1"># Calculate the shifts</span>
        <span class="n">nshifts</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">possible_c</span><span class="p">)</span>
        <span class="n">shifts</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nshifts</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="n">nshifts</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="c1"># There is an additional shift between the first and last c</span>
                <span class="c1"># coordinate. But this needs special handling because of PBC.</span>
                <span class="n">shift</span> <span class="o">=</span> <span class="p">(</span><span class="n">possible_c</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">possible_c</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">*</span> <span class="mf">0.5</span>
                <span class="k">if</span> <span class="n">shift</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
                    <span class="n">shift</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">shift</span> <span class="o">=</span> <span class="p">(</span><span class="n">possible_c</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">possible_c</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">*</span> <span class="mf">0.5</span>
            <span class="n">shifts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">shift</span> <span class="o">-</span> <span class="n">math</span><span class="o">.</span><span class="n">floor</span><span class="p">(</span><span class="n">shift</span><span class="p">))</span>
        <span class="n">shifts</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">shifts</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">shifts</span>

    <span class="k">def</span> <span class="nf">_get_c_ranges</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bonds</span><span class="p">):</span>
        <span class="n">c_ranges</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
        <span class="n">bonds</span> <span class="o">=</span> <span class="p">{(</span><span class="n">get_el_sp</span><span class="p">(</span><span class="n">s1</span><span class="p">),</span> <span class="n">get_el_sp</span><span class="p">(</span><span class="n">s2</span><span class="p">)):</span> <span class="n">dist</span> <span class="k">for</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">),</span> <span class="n">dist</span> <span class="ow">in</span>
                 <span class="n">bonds</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">sp1</span><span class="p">,</span> <span class="n">sp2</span><span class="p">),</span> <span class="n">bond_dist</span> <span class="ow">in</span> <span class="n">bonds</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">sp1</span> <span class="ow">in</span> <span class="n">site</span><span class="o">.</span><span class="n">species</span><span class="p">:</span>
                    <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">site</span><span class="p">,</span> <span class="n">bond_dist</span><span class="p">):</span>
                        <span class="k">if</span> <span class="n">sp2</span> <span class="ow">in</span> <span class="n">nn</span><span class="o">.</span><span class="n">species</span><span class="p">:</span>
                            <span class="n">c_range</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">([</span><span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span>
                                                    <span class="n">nn</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]]))</span>
                            <span class="k">if</span> <span class="n">c_range</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
                                <span class="c1"># Takes care of PBC when c coordinate of site</span>
                                <span class="c1"># goes beyond the upper boundary of the cell</span>
                                <span class="n">c_ranges</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">c_range</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">1</span><span class="p">))</span>
                                <span class="n">c_ranges</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="n">c_range</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
                            <span class="k">elif</span> <span class="n">c_range</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
                                <span class="c1"># Takes care of PBC when c coordinate of site</span>
                                <span class="c1"># is below the lower boundary of the unit cell</span>
                                <span class="n">c_ranges</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="n">c_range</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
                                <span class="n">c_ranges</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">c_range</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
                            <span class="k">elif</span> <span class="n">c_range</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">c_range</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
                                <span class="n">c_ranges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">c_range</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">c_ranges</span>

<div class="viewcode-block" id="SlabGenerator.get_slabs"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.SlabGenerator.get_slabs">[docs]</a>    <span class="k">def</span> <span class="nf">get_slabs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bonds</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">ftol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">max_broken_bonds</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
                  <span class="n">symmetrize</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">repair</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method returns a list of slabs that are generated using the list of</span>
<span class="sd">        shift values from the method, _calculate_possible_shifts(). Before the</span>
<span class="sd">        shifts are used to create the slabs however, if the user decides to take</span>
<span class="sd">        into account whether or not a termination will break any polyhedral</span>
<span class="sd">        structure (bonds is not None), this method will filter out any shift</span>
<span class="sd">        values that do so.</span>

<span class="sd">        Args:</span>
<span class="sd">            bonds ({(specie1, specie2): max_bond_dist}: bonds are</span>
<span class="sd">                specified as a dict of tuples: float of specie1, specie2</span>
<span class="sd">                and the max bonding distance. For example, PO4 groups may be</span>
<span class="sd">                defined as {(&quot;P&quot;, &quot;O&quot;): 3}.</span>
<span class="sd">            tol (float): General tolerance paramter for getting primitive</span>
<span class="sd">                cells and matching structures</span>
<span class="sd">            ftol (float): Threshold parameter in fcluster in order to check</span>
<span class="sd">                if two atoms are lying on the same plane. Default thresh set</span>
<span class="sd">                to 0.1 Angstrom in the direction of the surface normal.</span>
<span class="sd">            max_broken_bonds (int): Maximum number of allowable broken bonds</span>
<span class="sd">                for the slab. Use this to limit # of slabs (some structures</span>
<span class="sd">                may have a lot of slabs). Defaults to zero, which means no</span>
<span class="sd">                defined bonds must be broken.</span>
<span class="sd">            symmetrize (bool): Whether or not to ensure the surfaces of the</span>
<span class="sd">                slabs are equivalent.</span>
<span class="sd">            repair (bool): Whether to repair terminations with broken bonds</span>
<span class="sd">                or just omit them. Set to False as repairing terminations can</span>
<span class="sd">                lead to many possible slabs as oppose to just omitting them.</span>

<span class="sd">        Returns:</span>
<span class="sd">            ([Slab]) List of all possible terminations of a particular surface.</span>
<span class="sd">            Slabs are sorted by the # of bonds broken.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">c_ranges</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span> <span class="k">if</span> <span class="n">bonds</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_c_ranges</span><span class="p">(</span><span class="n">bonds</span><span class="p">)</span>

        <span class="n">slabs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">shift</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_calculate_possible_shifts</span><span class="p">(</span><span class="n">tol</span><span class="o">=</span><span class="n">ftol</span><span class="p">):</span>
            <span class="n">bonds_broken</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">c_ranges</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">r</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="n">shift</span> <span class="o">&lt;=</span> <span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
                    <span class="n">bonds_broken</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="n">slab</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_slab</span><span class="p">(</span><span class="n">shift</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="n">tol</span><span class="p">,</span> <span class="n">energy</span><span class="o">=</span><span class="n">bonds_broken</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">bonds_broken</span> <span class="o">&lt;=</span> <span class="n">max_broken_bonds</span><span class="p">:</span>
                <span class="n">slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">repair</span><span class="p">:</span>
                <span class="c1"># If the number of broken bonds is exceeded,</span>
                <span class="c1"># we repair the broken bonds on the slab</span>
                <span class="n">slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">repair_broken_bonds</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">bonds</span><span class="p">))</span>

        <span class="c1"># Further filters out any surfaces made that might be the same</span>
        <span class="n">m</span> <span class="o">=</span> <span class="n">StructureMatcher</span><span class="p">(</span><span class="n">ltol</span><span class="o">=</span><span class="n">tol</span><span class="p">,</span> <span class="n">stol</span><span class="o">=</span><span class="n">tol</span><span class="p">,</span> <span class="n">primitive_cell</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                             <span class="n">scale</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

        <span class="n">new_slabs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">group_structures</span><span class="p">(</span><span class="n">slabs</span><span class="p">):</span>
            <span class="c1"># For each unique termination, symmetrize the</span>
            <span class="c1"># surfaces by removing sites from the bottom.</span>
            <span class="k">if</span> <span class="n">symmetrize</span><span class="p">:</span>
                <span class="n">slabs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nonstoichiometric_symmetrized_slab</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
                <span class="n">new_slabs</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">slabs</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">new_slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

        <span class="n">match</span> <span class="o">=</span> <span class="n">StructureMatcher</span><span class="p">(</span><span class="n">ltol</span><span class="o">=</span><span class="n">tol</span><span class="p">,</span> <span class="n">stol</span><span class="o">=</span><span class="n">tol</span><span class="p">,</span> <span class="n">primitive_cell</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                                 <span class="n">scale</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
        <span class="n">new_slabs</span> <span class="o">=</span> <span class="p">[</span><span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">match</span><span class="o">.</span><span class="n">group_structures</span><span class="p">(</span><span class="n">new_slabs</span><span class="p">)]</span>

        <span class="k">return</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">new_slabs</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">s</span><span class="o">.</span><span class="n">energy</span><span class="p">)</span></div>

<div class="viewcode-block" id="SlabGenerator.repair_broken_bonds"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.SlabGenerator.repair_broken_bonds">[docs]</a>    <span class="k">def</span> <span class="nf">repair_broken_bonds</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">slab</span><span class="p">,</span> <span class="n">bonds</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method will find undercoordinated atoms due to slab</span>
<span class="sd">        cleaving specified by the bonds parameter and move them</span>
<span class="sd">        to the other surface to make sure the bond is kept intact.</span>
<span class="sd">        In a future release of surface.py, the ghost_sites will be</span>
<span class="sd">        used to tell us how the repair bonds should look like.</span>

<span class="sd">        Arg:</span>
<span class="sd">            slab (structure): A structure object representing a slab.</span>
<span class="sd">            bonds ({(specie1, specie2): max_bond_dist}: bonds are</span>
<span class="sd">                specified as a dict of tuples: float of specie1, specie2</span>
<span class="sd">                and the max bonding distance. For example, PO4 groups may be</span>
<span class="sd">                defined as {(&quot;P&quot;, &quot;O&quot;): 3}.</span>

<span class="sd">        Returns:</span>
<span class="sd">            (Slab) A Slab object with a particular shifted oriented unit cell.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">bonds</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
            <span class="n">blength</span> <span class="o">=</span> <span class="n">bonds</span><span class="p">[</span><span class="n">pair</span><span class="p">]</span>

            <span class="c1"># First lets determine which element should be the</span>
            <span class="c1"># reference (center element) to determine broken bonds.</span>
            <span class="c1"># e.g. P for a PO4 bond. Find integer coordination</span>
            <span class="c1"># numbers of the pair of elements wrt to each other</span>
            <span class="n">cn_dict</span> <span class="o">=</span> <span class="p">{}</span>
            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">el</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pair</span><span class="p">):</span>
                <span class="n">cnlist</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">:</span>
                    <span class="n">poly_coord</span> <span class="o">=</span> <span class="mi">0</span>
                    <span class="k">if</span> <span class="n">site</span><span class="o">.</span><span class="n">species_string</span> <span class="o">==</span> <span class="n">el</span><span class="p">:</span>

                        <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span>
                                <span class="n">site</span><span class="p">,</span> <span class="n">blength</span><span class="p">):</span>
                            <span class="k">if</span> <span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">species_string</span> <span class="o">==</span> <span class="n">pair</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]:</span>
                                <span class="n">poly_coord</span> <span class="o">+=</span> <span class="mi">1</span>
                    <span class="n">cnlist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">poly_coord</span><span class="p">)</span>
                <span class="n">cn_dict</span><span class="p">[</span><span class="n">el</span><span class="p">]</span> <span class="o">=</span> <span class="n">cnlist</span>

            <span class="c1"># We make the element with the higher coordination our reference</span>
            <span class="k">if</span> <span class="nb">max</span><span class="p">(</span><span class="n">cn_dict</span><span class="p">[</span><span class="n">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]])</span> <span class="o">&gt;</span> <span class="nb">max</span><span class="p">(</span><span class="n">cn_dict</span><span class="p">[</span><span class="n">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]):</span>
                <span class="n">element1</span><span class="p">,</span> <span class="n">element2</span> <span class="o">=</span> <span class="n">pair</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">element2</span><span class="p">,</span> <span class="n">element1</span> <span class="o">=</span> <span class="n">pair</span>

            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">slab</span><span class="p">):</span>
                <span class="c1"># Determine the coordination of our reference</span>
                <span class="k">if</span> <span class="n">site</span><span class="o">.</span><span class="n">species_string</span> <span class="o">==</span> <span class="n">element1</span><span class="p">:</span>
                    <span class="n">poly_coord</span> <span class="o">=</span> <span class="mi">0</span>
                    <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">site</span><span class="p">,</span> <span class="n">blength</span><span class="p">):</span>
                        <span class="n">poly_coord</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">neighbor</span><span class="o">.</span><span class="n">species_string</span> <span class="o">==</span> <span class="n">element2</span> <span class="k">else</span> <span class="mi">0</span>

                    <span class="c1"># suppose we find an undercoordinated reference atom</span>
                    <span class="k">if</span> <span class="n">poly_coord</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cn_dict</span><span class="p">[</span><span class="n">element1</span><span class="p">]:</span>
                        <span class="c1"># We get the reference atom of the broken bonds</span>
                        <span class="c1"># (undercoordinated), move it to the other surface</span>
                        <span class="n">slab</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">move_to_other_side</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="p">[</span><span class="n">i</span><span class="p">])</span>

                        <span class="c1"># find its NNs with the corresponding</span>
                        <span class="c1"># species it should be coordinated with</span>
                        <span class="n">neighbors</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">slab</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">blength</span><span class="p">,</span>
                                                       <span class="n">include_index</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
                        <span class="n">tomove</span> <span class="o">=</span> <span class="p">[</span><span class="n">nn</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span> <span class="n">neighbors</span> <span class="k">if</span>
                                  <span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">species_string</span> <span class="o">==</span> <span class="n">element2</span><span class="p">]</span>
                        <span class="n">tomove</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
                        <span class="c1"># and then move those NNs along with the central</span>
                        <span class="c1"># atom back to the other side of the slab again</span>
                        <span class="n">slab</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">move_to_other_side</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">tomove</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">slab</span></div>

<div class="viewcode-block" id="SlabGenerator.move_to_other_side"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.SlabGenerator.move_to_other_side">[docs]</a>    <span class="k">def</span> <span class="nf">move_to_other_side</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">init_slab</span><span class="p">,</span> <span class="n">index_of_sites</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method will Move a set of sites to the</span>
<span class="sd">        other side of the slab (opposite surface).</span>

<span class="sd">        Arg:</span>
<span class="sd">            init_slab (structure): A structure object representing a slab.</span>
<span class="sd">            index_of_sites (list of ints): The list of indices representing</span>
<span class="sd">                the sites we want to move to the other side.</span>

<span class="sd">        Returns:</span>
<span class="sd">            (Slab) A Slab object with a particular shifted oriented unit cell.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">slab</span> <span class="o">=</span> <span class="n">init_slab</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>

        <span class="c1"># Determine what fraction the slab is of the total cell size</span>
        <span class="c1"># in the c direction. Round to nearest rational number.</span>
        <span class="n">h</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_proj_height</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">h</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">d_hkl</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">in_unit_planes</span><span class="p">:</span>
            <span class="n">nlayers_slab</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span> <span class="o">/</span> <span class="n">p</span><span class="p">))</span>
            <span class="n">nlayers_vac</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_vac_size</span> <span class="o">/</span> <span class="n">p</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">nlayers_slab</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span> <span class="o">/</span> <span class="n">h</span><span class="p">))</span>
            <span class="n">nlayers_vac</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_vac_size</span> <span class="o">/</span> <span class="n">h</span><span class="p">))</span>
        <span class="n">nlayers</span> <span class="o">=</span> <span class="n">nlayers_slab</span> <span class="o">+</span> <span class="n">nlayers_vac</span>
        <span class="n">slab_ratio</span> <span class="o">=</span> <span class="n">nlayers_slab</span> <span class="o">/</span> <span class="n">nlayers</span>

        <span class="c1"># Sort the index of sites based on which side they are on</span>
        <span class="n">top_site_index</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">index_of_sites</span> <span class="k">if</span>
                          <span class="n">slab</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">slab</span><span class="o">.</span><span class="n">center_of_mass</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
        <span class="n">bottom_site_index</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">index_of_sites</span> <span class="k">if</span>
                             <span class="n">slab</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">slab</span><span class="o">.</span><span class="n">center_of_mass</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>

        <span class="c1"># Translate sites to the opposite surfaces</span>
        <span class="n">slab</span><span class="o">.</span><span class="n">translate_sites</span><span class="p">(</span><span class="n">top_site_index</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">slab_ratio</span><span class="p">])</span>
        <span class="n">slab</span><span class="o">.</span><span class="n">translate_sites</span><span class="p">(</span><span class="n">bottom_site_index</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="n">slab_ratio</span><span class="p">])</span>

        <span class="k">return</span> <span class="n">Slab</span><span class="p">(</span><span class="n">init_slab</span><span class="o">.</span><span class="n">lattice</span><span class="p">,</span> <span class="n">slab</span><span class="o">.</span><span class="n">species</span><span class="p">,</span> <span class="n">slab</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span>
                    <span class="n">init_slab</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span> <span class="n">init_slab</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="p">,</span>
                    <span class="n">init_slab</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span> <span class="n">init_slab</span><span class="o">.</span><span class="n">scale_factor</span><span class="p">,</span>
                    <span class="n">energy</span><span class="o">=</span><span class="n">init_slab</span><span class="o">.</span><span class="n">energy</span><span class="p">)</span></div>

<div class="viewcode-block" id="SlabGenerator.nonstoichiometric_symmetrized_slab"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.SlabGenerator.nonstoichiometric_symmetrized_slab">[docs]</a>    <span class="k">def</span> <span class="nf">nonstoichiometric_symmetrized_slab</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">init_slab</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method checks whether or not the two surfaces of the slab are</span>
<span class="sd">        equivalent. If the point group of the slab has an inversion symmetry (</span>
<span class="sd">        ie. belong to one of the Laue groups), then it is assumed that the</span>
<span class="sd">        surfaces should be equivalent. Otherwise, sites at the bottom of the</span>
<span class="sd">        slab will be removed until the slab is symmetric. Note the removal of sites</span>
<span class="sd">        can destroy the stoichiometry of the slab. For non-elemental</span>
<span class="sd">        structures, the chemical potential will be needed to calculate surface energy.</span>

<span class="sd">        Arg:</span>
<span class="sd">            init_slab (Structure): A single slab structure</span>
<span class="sd">            tol (float): Tolerance for SpaceGroupanalyzer.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Slab (structure): A symmetrized Slab object.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">init_slab</span><span class="p">,</span> <span class="n">symprec</span><span class="o">=</span><span class="n">tol</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">sg</span><span class="o">.</span><span class="n">is_laue</span><span class="p">():</span>
            <span class="k">return</span> <span class="p">[</span><span class="n">init_slab</span><span class="p">]</span>

        <span class="n">nonstoich_slabs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="c1"># Build an equivalent surface slab for each of the different surfaces</span>
        <span class="k">for</span> <span class="n">top</span> <span class="ow">in</span> <span class="p">[</span><span class="kc">True</span><span class="p">,</span> <span class="kc">False</span><span class="p">]:</span>
            <span class="n">asym</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="n">slab</span> <span class="o">=</span> <span class="n">init_slab</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">energy</span> <span class="o">=</span> <span class="n">init_slab</span><span class="o">.</span><span class="n">energy</span>

            <span class="k">while</span> <span class="n">asym</span><span class="p">:</span>
                <span class="c1"># Keep removing sites from the bottom one by one until both</span>
                <span class="c1"># surfaces are symmetric or the number of sites removed has</span>
                <span class="c1"># exceeded 10 percent of the original slab</span>

                <span class="n">c_dir</span> <span class="o">=</span> <span class="p">[</span><span class="n">site</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">slab</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">)]</span>

                <span class="k">if</span> <span class="n">top</span><span class="p">:</span>
                    <span class="n">slab</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">([</span><span class="n">c_dir</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">c_dir</span><span class="p">))])</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">slab</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">([</span><span class="n">c_dir</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">c_dir</span><span class="p">))])</span>
                <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="p">):</span>
                    <span class="k">break</span>

                <span class="c1"># Check if the altered surface is symmetric</span>
                <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">symprec</span><span class="o">=</span><span class="n">tol</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">sg</span><span class="o">.</span><span class="n">is_laue</span><span class="p">():</span>
                    <span class="n">asym</span> <span class="o">=</span> <span class="kc">False</span>
                    <span class="n">nonstoich_slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent</span><span class="p">):</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">&quot;Too many sites removed, please use a larger slab &quot;</span>
                          <span class="s2">&quot;size.&quot;</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">nonstoich_slabs</span></div></div>


<span class="n">module_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="vm">__file__</span><span class="p">))</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">module_dir</span><span class="p">,</span>
                       <span class="s2">&quot;reconstructions_archive.json&quot;</span><span class="p">))</span> <span class="k">as</span> <span class="n">data_file</span><span class="p">:</span>
    <span class="n">reconstructions_archive</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">data_file</span><span class="p">)</span>


<div class="viewcode-block" id="ReconstructionGenerator"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.ReconstructionGenerator">[docs]</a><span class="k">class</span> <span class="nc">ReconstructionGenerator</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This class takes in a pre-defined dictionary specifying the parameters</span>
<span class="sd">    need to build a reconstructed slab such as the SlabGenerator parameters,</span>
<span class="sd">    transformation matrix, sites to remove/add and slab/vacuum size. It will</span>
<span class="sd">    then use the formatted instructions provided by the dictionary to build</span>
<span class="sd">    the desired reconstructed slab from the initial structure.</span>

<span class="sd">    .. attribute:: slabgen_params</span>

<span class="sd">        Parameters for the SlabGenerator</span>

<span class="sd">    .. trans_matrix::</span>

<span class="sd">        A 3x3 transformation matrix to generate the reconstructed</span>
<span class="sd">            slab. Only the a and b lattice vectors are actually</span>
<span class="sd">            changed while the c vector remains the same. This</span>
<span class="sd">            matrix is what the Wood&#39;s notation is based on.</span>

<span class="sd">    .. reconstruction_json::</span>

<span class="sd">        The full json or dictionary containing the instructions</span>
<span class="sd">            for building the reconstructed slab</span>

<span class="sd">    .. termination::</span>

<span class="sd">        The index of the termination of the slab</span>

<span class="sd">    TODO:</span>
<span class="sd">    - Right now there is no way to specify what atom is being</span>
<span class="sd">        added. In the future, use basis sets?</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">initial_structure</span><span class="p">,</span> <span class="n">min_slab_size</span><span class="p">,</span>
                 <span class="n">min_vacuum_size</span><span class="p">,</span> <span class="n">reconstruction_name</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Generates reconstructed slabs from a set of instructions</span>
<span class="sd">            specified by a dictionary or json file.</span>

<span class="sd">        Args:</span>
<span class="sd">            initial_structure (Structure): Initial input structure. Note</span>
<span class="sd">                that to ensure that the miller indices correspond to usual</span>
<span class="sd">                crystallographic definitions, you should supply a conventional</span>
<span class="sd">                unit cell structure.</span>
<span class="sd">            min_slab_size (float): In Angstroms</span>
<span class="sd">            min_vacuum_size (float): In Angstroms</span>

<span class="sd">            reconstruction (str): Name of the dict containing the instructions</span>
<span class="sd">                for building a reconstructed slab. The dictionary can contain</span>
<span class="sd">                any item the creator deems relevant, however any instructions</span>
<span class="sd">                archived in pymatgen for public use needs to contain the</span>
<span class="sd">                following keys and items to ensure compatibility with the</span>
<span class="sd">                ReconstructionGenerator:</span>

<span class="sd">                    &quot;name&quot; (str): A descriptive name for the type of</span>
<span class="sd">                        reconstruction. Typically the name will have the type</span>
<span class="sd">                        of structure the reconstruction is for, the Miller</span>
<span class="sd">                        index, and Wood&#39;s notation along with anything to</span>
<span class="sd">                        describe the reconstruction: e.g.:</span>
<span class="sd">                        &quot;fcc_110_missing_row_1x2&quot;</span>
<span class="sd">                    &quot;description&quot; (str): A longer description of your</span>
<span class="sd">                        reconstruction. This is to help future contributors who</span>
<span class="sd">                        want to add other types of reconstructions to the</span>
<span class="sd">                        archive on pymatgen to check if the reconstruction</span>
<span class="sd">                        already exists. Please read the descriptions carefully</span>
<span class="sd">                        before adding a new type of reconstruction to ensure it</span>
<span class="sd">                        is not in the archive yet.</span>
<span class="sd">                    &quot;reference&quot; (str): Optional reference to where the</span>
<span class="sd">                        reconstruction was taken from or first observed.</span>
<span class="sd">                    &quot;spacegroup&quot; (dict): e.g. {&quot;symbol&quot;: &quot;Fm-3m&quot;, &quot;number&quot;: 225}</span>
<span class="sd">                        Indicates what kind of structure is this reconstruction.</span>
<span class="sd">                    &quot;miller_index&quot; ([h,k,l]): Miller index of your reconstruction</span>
<span class="sd">                    &quot;Woods_notation&quot; (str): For a reconstruction, the a and b</span>
<span class="sd">                        lattice may change to accomodate the symmetry of the</span>
<span class="sd">                        reconstruction. This notation indicates the change in</span>
<span class="sd">                        the vectors relative to the primitive (p) or</span>
<span class="sd">                        conventional (c) slab cell. E.g. p(2x1):</span>

<span class="sd">                        Wood, E. A. (1964). Vocabulary of surface</span>
<span class="sd">                        crystallography. Journal of Applied Physics, 35(4),</span>
<span class="sd">                        1306–1312.</span>

<span class="sd">                    &quot;transformation_matrix&quot; (numpy array): A 3x3 matrix to</span>
<span class="sd">                        transform the slab. Only the a and b lattice vectors</span>
<span class="sd">                        should change while the c vector remains the same.</span>
<span class="sd">                    &quot;SlabGenerator_parameters&quot; (dict): A dictionary containing</span>
<span class="sd">                        the parameters for the SlabGenerator class excluding the</span>
<span class="sd">                        miller_index, min_slab_size and min_vac_size as the</span>
<span class="sd">                        Miller index is already specified and the min_slab_size</span>
<span class="sd">                        and min_vac_size can be changed regardless of what type</span>
<span class="sd">                        of reconstruction is used. Having a consistent set of</span>
<span class="sd">                        SlabGenerator parameters allows for the instructions to</span>
<span class="sd">                        be reused to consistently build a reconstructed slab.</span>
<span class="sd">                    &quot;points_to_remove&quot; (list of coords): A list of sites to</span>
<span class="sd">                        remove where the first two indices are fraction (in a</span>
<span class="sd">                        and b) and the third index is in units of 1/d (in c).</span>
<span class="sd">                    &quot;points_to_add&quot; (list of frac_coords): A list of sites to add</span>
<span class="sd">                        where the first two indices are fraction (in a an b) and</span>
<span class="sd">                        the third index is in units of 1/d (in c).</span>

<span class="sd">                    &quot;base_reconstruction&quot; (dict): Option to base a reconstruction on</span>
<span class="sd">                        an existing reconstruction model also exists to easily build</span>
<span class="sd">                        the instructions without repeating previous work. E.g. the</span>
<span class="sd">                        alpha reconstruction of halites is based on the octopolar</span>
<span class="sd">                        reconstruction but with the topmost atom removed. The dictionary</span>
<span class="sd">                        for the alpha reconstruction would therefore contain the item</span>
<span class="sd">                        &quot;reconstruction_base&quot;: &quot;halite_111_octopolar_2x2&quot;, and</span>
<span class="sd">                        additional sites for &quot;points_to_remove&quot; and &quot;points_to_add&quot;</span>
<span class="sd">                        can be added to modify this reconstruction.</span>

<span class="sd">                    For &quot;points_to_remove&quot; and &quot;points_to_add&quot;, the third index for</span>
<span class="sd">                        the c vector is in units of 1/d where d is the spacing</span>
<span class="sd">                        between atoms along hkl (the c vector) and is relative to</span>
<span class="sd">                        the topmost site in the unreconstructed slab. e.g. a point</span>
<span class="sd">                        of [0.5, 0.25, 1] corresponds to the 0.5 frac_coord of a,</span>
<span class="sd">                        0.25 frac_coord of b and a distance of 1 atomic layer above</span>
<span class="sd">                        the topmost site. [0.5, 0.25, -0.5] where the third index</span>
<span class="sd">                        corresponds to a point half a atomic layer below the topmost</span>
<span class="sd">                        site. [0.5, 0.25, 0] corresponds to a point in the same</span>
<span class="sd">                        position along c as the topmost site. This is done because</span>
<span class="sd">                        while the primitive units of a and b will remain constant,</span>
<span class="sd">                        the user can vary the length of the c direction by changing</span>
<span class="sd">                        the slab layer or the vacuum layer.</span>

<span class="sd">            NOTE: THE DICTIONARY SHOULD ONLY CONTAIN &quot;points_to_remove&quot; AND</span>
<span class="sd">            &quot;points_to_add&quot; FOR THE TOP SURFACE. THE ReconstructionGenerator</span>
<span class="sd">            WILL MODIFY THE BOTTOM SURFACE ACCORDINGLY TO RETURN A SLAB WITH</span>
<span class="sd">            EQUIVALENT SURFACES.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="n">reconstruction_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">reconstructions_archive</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
            <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="s2">&quot;The reconstruction_name entered (</span><span class="si">%s</span><span class="s2">) does not exist in the &quot;</span>
                           <span class="s2">&quot;archive. Please select from one of the following reconstructions: </span><span class="si">%s</span><span class="s2"> &quot;</span>
                           <span class="s2">&quot;or add the appropriate dictionary to the archive file &quot;</span>
                           <span class="s2">&quot;reconstructions_archive.json.&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">reconstruction_name</span><span class="p">,</span>
                                                              <span class="nb">list</span><span class="p">(</span><span class="n">reconstructions_archive</span><span class="o">.</span><span class="n">keys</span><span class="p">())))</span>

        <span class="c1"># Get the instructions to build the reconstruction</span>
        <span class="c1"># from the reconstruction_archive</span>
        <span class="n">recon_json</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">reconstructions_archive</span><span class="p">[</span><span class="n">reconstruction_name</span><span class="p">])</span>
        <span class="n">new_points_to_add</span><span class="p">,</span> <span class="n">new_points_to_remove</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>
        <span class="k">if</span> <span class="s2">&quot;base_reconstruction&quot;</span> <span class="ow">in</span> <span class="n">recon_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
            <span class="k">if</span> <span class="s2">&quot;points_to_add&quot;</span> <span class="ow">in</span> <span class="n">recon_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="n">new_points_to_add</span> <span class="o">=</span> <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;points_to_add&quot;</span><span class="p">]</span>
            <span class="k">if</span> <span class="s2">&quot;points_to_remove&quot;</span> <span class="ow">in</span> <span class="n">recon_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="n">new_points_to_remove</span> <span class="o">=</span> <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;points_to_remove&quot;</span><span class="p">]</span>

            <span class="c1"># Build new instructions from a base reconstruction</span>
            <span class="n">recon_json</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">reconstructions_archive</span><span class="p">[</span><span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;base_reconstruction&quot;</span><span class="p">]])</span>
            <span class="k">if</span> <span class="s2">&quot;points_to_add&quot;</span> <span class="ow">in</span> <span class="n">recon_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="k">del</span> <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;points_to_add&quot;</span><span class="p">]</span>
            <span class="k">if</span> <span class="s2">&quot;points_to_remove&quot;</span> <span class="ow">in</span> <span class="n">recon_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="k">del</span> <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;points_to_remove&quot;</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">new_points_to_add</span><span class="p">:</span>
                <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;points_to_add&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_points_to_add</span>
            <span class="k">if</span> <span class="n">new_points_to_remove</span><span class="p">:</span>
                <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;points_to_remove&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_points_to_remove</span>

        <span class="n">slabgen_params</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;SlabGenerator_parameters&quot;</span><span class="p">])</span>
        <span class="n">slabgen_params</span><span class="p">[</span><span class="s2">&quot;initial_structure&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">initial_structure</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="n">slabgen_params</span><span class="p">[</span><span class="s2">&quot;miller_index&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;miller_index&quot;</span><span class="p">]</span>
        <span class="n">slabgen_params</span><span class="p">[</span><span class="s2">&quot;min_slab_size&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">min_slab_size</span>
        <span class="n">slabgen_params</span><span class="p">[</span><span class="s2">&quot;min_vacuum_size&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">min_vacuum_size</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">slabgen_params</span> <span class="o">=</span> <span class="n">slabgen_params</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">trans_matrix</span> <span class="o">=</span> <span class="n">recon_json</span><span class="p">[</span><span class="s2">&quot;transformation_matrix&quot;</span><span class="p">]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reconstruction_json</span> <span class="o">=</span> <span class="n">recon_json</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">reconstruction_name</span>

<div class="viewcode-block" id="ReconstructionGenerator.build_slabs"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.ReconstructionGenerator.build_slabs">[docs]</a>    <span class="k">def</span> <span class="nf">build_slabs</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Builds the reconstructed slab by:</span>
<span class="sd">            (1) Obtaining the unreconstructed slab using the specified</span>
<span class="sd">                parameters for the SlabGenerator.</span>
<span class="sd">            (2) Applying the appropriate lattice transformation in the</span>
<span class="sd">                a and b lattice vectors.</span>
<span class="sd">            (3) Remove any specified sites from both surfaces.</span>
<span class="sd">            (4) Add any specified sites to both surfaces.</span>

<span class="sd">        Returns:</span>
<span class="sd">            (Slab): The reconstructed slab.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">slabs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_unreconstructed_slabs</span><span class="p">()</span>
        <span class="n">recon_slabs</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">for</span> <span class="n">slab</span> <span class="ow">in</span> <span class="n">slabs</span><span class="p">:</span>
            <span class="n">d</span> <span class="o">=</span> <span class="n">get_d</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>
            <span class="n">top_site</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">site</span><span class="p">:</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">coords</span>

            <span class="c1"># Remove any specified sites</span>
            <span class="k">if</span> <span class="s2">&quot;points_to_remove&quot;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">reconstruction_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="n">pts_to_rm</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">reconstruction_json</span><span class="p">[</span><span class="s2">&quot;points_to_remove&quot;</span><span class="p">])</span>
                <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pts_to_rm</span><span class="p">:</span>
                    <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_fractional_coords</span><span class="p">([</span><span class="n">top_site</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">top_site</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
                                                               <span class="n">top_site</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="n">d</span><span class="p">])[</span><span class="mi">2</span><span class="p">]</span>
                    <span class="n">cart_point</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_cartesian_coords</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
                    <span class="n">dist</span> <span class="o">=</span> <span class="p">[</span><span class="n">site</span><span class="o">.</span><span class="n">distance_from_point</span><span class="p">(</span><span class="n">cart_point</span><span class="p">)</span> <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">slab</span><span class="p">]</span>
                    <span class="n">site1</span> <span class="o">=</span> <span class="n">dist</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">dist</span><span class="p">))</span>
                    <span class="n">slab</span><span class="o">.</span><span class="n">symmetrically_remove_atoms</span><span class="p">([</span><span class="n">site1</span><span class="p">])</span>

            <span class="c1"># Add any specified sites</span>
            <span class="k">if</span> <span class="s2">&quot;points_to_add&quot;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">reconstruction_json</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="n">pts_to_add</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">reconstruction_json</span><span class="p">[</span><span class="s2">&quot;points_to_add&quot;</span><span class="p">])</span>
                <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pts_to_add</span><span class="p">:</span>
                    <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_fractional_coords</span><span class="p">([</span><span class="n">top_site</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">top_site</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
                                                               <span class="n">top_site</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">p</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="n">d</span><span class="p">])[</span><span class="mi">2</span><span class="p">]</span>
                    <span class="n">slab</span><span class="o">.</span><span class="n">symmetrically_add_atom</span><span class="p">(</span><span class="n">slab</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">specie</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>

            <span class="n">slab</span><span class="o">.</span><span class="n">reconstruction</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
            <span class="nb">setattr</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="s2">&quot;recon_trans_matrix&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">trans_matrix</span><span class="p">)</span>

            <span class="c1"># Get the oriented_unit_cell with the same axb area.</span>
            <span class="n">ouc</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">oriented_unit_cell</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">ouc</span><span class="o">.</span><span class="n">make_supercell</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">trans_matrix</span><span class="p">)</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">oriented_unit_cell</span> <span class="o">=</span> <span class="n">ouc</span>
            <span class="n">recon_slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">recon_slabs</span></div>

<div class="viewcode-block" id="ReconstructionGenerator.get_unreconstructed_slabs"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.ReconstructionGenerator.get_unreconstructed_slabs">[docs]</a>    <span class="k">def</span> <span class="nf">get_unreconstructed_slabs</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Generates the unreconstructed or pristine super slab.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">slabs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">slab</span> <span class="ow">in</span> <span class="n">SlabGenerator</span><span class="p">(</span><span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">slabgen_params</span><span class="p">)</span><span class="o">.</span><span class="n">get_slabs</span><span class="p">():</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">make_supercell</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">trans_matrix</span><span class="p">)</span>
            <span class="n">slabs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">slab</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">slabs</span></div></div>


<div class="viewcode-block" id="get_d"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.get_d">[docs]</a><span class="k">def</span> <span class="nf">get_d</span><span class="p">(</span><span class="n">slab</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Determine the distance of space between</span>
<span class="sd">    each layer of atoms along c</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">sorted_sites</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">site</span><span class="p">:</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">sorted_sites</span><span class="p">):</span>
        <span class="k">if</span> <span class="s2">&quot;</span><span class="si">%.6f</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="o">==</span> <span class="s2">&quot;</span><span class="si">%.6f</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">sorted_sites</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]):</span>
            <span class="k">continue</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">d</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">sorted_sites</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
            <span class="k">break</span>
    <span class="k">return</span> <span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_cartesian_coords</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">d</span><span class="p">])[</span><span class="mi">2</span><span class="p">]</span></div>


<div class="viewcode-block" id="is_already_analyzed"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.is_already_analyzed">[docs]</a><span class="k">def</span> <span class="nf">is_already_analyzed</span><span class="p">(</span>
        <span class="n">miller_index</span><span class="p">:</span> <span class="nb">tuple</span><span class="p">,</span> <span class="n">miller_list</span><span class="p">:</span> <span class="nb">list</span><span class="p">,</span> <span class="n">symm_ops</span><span class="p">:</span> <span class="nb">list</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Helper function to check if a given Miller index is</span>
<span class="sd">    part of the family of indices of any index in a list</span>

<span class="sd">    Args:</span>
<span class="sd">        miller_index (tuple): The Miller index to analyze</span>
<span class="sd">        miller_list (list): List of Miller indices. If the given</span>
<span class="sd">            Miller index belongs in the same family as any of the</span>
<span class="sd">            indices in this list, return True, else return False</span>
<span class="sd">        symm_ops (list): Symmetry operations of a</span>
<span class="sd">            lattice, used to define family of indices</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">for</span> <span class="n">op</span> <span class="ow">in</span> <span class="n">symm_ops</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">in_coord_list</span><span class="p">(</span><span class="n">miller_list</span><span class="p">,</span> <span class="n">op</span><span class="o">.</span><span class="n">operate</span><span class="p">(</span><span class="n">miller_index</span><span class="p">)):</span>
            <span class="k">return</span> <span class="kc">True</span>
    <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="get_symmetrically_equivalent_miller_indices"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.get_symmetrically_equivalent_miller_indices">[docs]</a><span class="k">def</span> <span class="nf">get_symmetrically_equivalent_miller_indices</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">miller_index</span><span class="p">,</span> <span class="n">return_hkil</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Returns all symmetrically equivalent indices for a given structure. Analysis</span>
<span class="sd">    is based on the symmetry of the reciprocal lattice of the structure.</span>

<span class="sd">    Args:</span>
<span class="sd">        miller_index (tuple): Designates the family of Miller indices</span>
<span class="sd">            to find. Can be hkl or hkil for hexagonal systems</span>
<span class="sd">        return_hkil (bool): If true, return hkil form of Miller</span>
<span class="sd">            index for hexagonal systems, otherwise return hkl</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c1"># Change to hkl if hkil because in_coord_list only handles tuples of 3</span>
    <span class="n">miller_index</span> <span class="o">=</span> <span class="p">(</span><span class="n">miller_index</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">miller_index</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">miller_index</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span> \
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">miller_index</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span> <span class="k">else</span> <span class="n">miller_index</span>
    <span class="n">mmi</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">miller_index</span><span class="p">))</span>
    <span class="n">r</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="n">mmi</span><span class="p">,</span> <span class="n">mmi</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="n">r</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>

    <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
    <span class="c1"># Get distinct hkl planes from the rhombohedral setting if trigonal</span>
    <span class="k">if</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_crystal_system</span><span class="p">()</span> <span class="o">==</span> <span class="s2">&quot;trigonal&quot;</span><span class="p">:</span>
        <span class="n">prim_structure</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span><span class="o">.</span><span class="n">get_primitive_standard_structure</span><span class="p">()</span>
        <span class="n">symm_ops</span> <span class="o">=</span> <span class="n">prim_structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_recp_symmetry_operation</span><span class="p">()</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">symm_ops</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_recp_symmetry_operation</span><span class="p">()</span>

    <span class="n">equivalent_millers</span> <span class="o">=</span> <span class="p">[</span><span class="n">miller_index</span><span class="p">]</span>
    <span class="k">for</span> <span class="n">miller</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">r</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">miller</span> <span class="o">==</span> <span class="n">miller_index</span><span class="p">:</span>
            <span class="k">continue</span>
        <span class="k">if</span> <span class="nb">any</span><span class="p">([</span><span class="n">i</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">miller</span><span class="p">]):</span>
            <span class="k">if</span> <span class="n">is_already_analyzed</span><span class="p">(</span><span class="n">miller</span><span class="p">,</span> <span class="n">equivalent_millers</span><span class="p">,</span> <span class="n">symm_ops</span><span class="p">):</span>
                <span class="n">equivalent_millers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">miller</span><span class="p">)</span>

            <span class="c1"># include larger Miller indices in the family of planes</span>
            <span class="k">if</span> <span class="nb">all</span><span class="p">([</span><span class="n">mmi</span> <span class="o">&gt;</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">miller</span><span class="p">)])</span> <span class="ow">and</span> \
                    <span class="ow">not</span> <span class="n">in_coord_list</span><span class="p">(</span><span class="n">equivalent_millers</span><span class="p">,</span> <span class="n">miller</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">is_already_analyzed</span><span class="p">(</span><span class="n">mmi</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">miller</span><span class="p">),</span>
                                       <span class="n">equivalent_millers</span><span class="p">,</span> <span class="n">symm_ops</span><span class="p">):</span>
                    <span class="n">equivalent_millers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">miller</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">return_hkil</span> <span class="ow">and</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_crystal_system</span><span class="p">()</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;trigonal&quot;</span><span class="p">,</span> <span class="s2">&quot;hexagonal&quot;</span><span class="p">]:</span>
        <span class="k">return</span> <span class="p">[(</span><span class="n">hkl</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">hkl</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">hkl</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">hkl</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
                 <span class="n">hkl</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">for</span> <span class="n">hkl</span> <span class="ow">in</span> <span class="n">equivalent_millers</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">equivalent_millers</span></div>


<div class="viewcode-block" id="get_symmetrically_distinct_miller_indices"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.get_symmetrically_distinct_miller_indices">[docs]</a><span class="k">def</span> <span class="nf">get_symmetrically_distinct_miller_indices</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">max_index</span><span class="p">,</span> <span class="n">return_hkil</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Returns all symmetrically distinct indices below a certain max-index for</span>
<span class="sd">    a given structure. Analysis is based on the symmetry of the reciprocal</span>
<span class="sd">    lattice of the structure.</span>
<span class="sd">    Args:</span>
<span class="sd">        structure (Structure): input structure.</span>
<span class="sd">        max_index (int): The maximum index. For example, a max_index of 1</span>
<span class="sd">            means that (100), (110), and (111) are returned for the cubic</span>
<span class="sd">            structure. All other indices are equivalent to one of these.</span>
<span class="sd">        return_hkil (bool): If true, return hkil form of Miller</span>
<span class="sd">            index for hexagonal systems, otherwise return hkl</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">r</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="n">max_index</span><span class="p">,</span> <span class="n">max_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="n">r</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>

    <span class="c1"># First we get a list of all hkls for conventional (including equivalent)</span>
    <span class="n">conv_hkl_list</span> <span class="o">=</span> <span class="p">[</span><span class="n">miller</span> <span class="k">for</span> <span class="n">miller</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="k">if</span> <span class="nb">any</span><span class="p">([</span><span class="n">i</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">miller</span><span class="p">])]</span>

    <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
    <span class="c1"># Get distinct hkl planes from the rhombohedral setting if trigonal</span>
    <span class="k">if</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_crystal_system</span><span class="p">()</span> <span class="o">==</span> <span class="s2">&quot;trigonal&quot;</span><span class="p">:</span>
        <span class="n">transf</span> <span class="o">=</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_conventional_to_primitive_transformation_matrix</span><span class="p">()</span>
        <span class="n">miller_list</span> <span class="o">=</span> <span class="p">[</span><span class="n">hkl_transformation</span><span class="p">(</span><span class="n">transf</span><span class="p">,</span> <span class="n">hkl</span><span class="p">)</span> <span class="k">for</span> <span class="n">hkl</span> <span class="ow">in</span> <span class="n">conv_hkl_list</span><span class="p">]</span>
        <span class="n">prim_structure</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span><span class="o">.</span><span class="n">get_primitive_standard_structure</span><span class="p">()</span>
        <span class="n">symm_ops</span> <span class="o">=</span> <span class="n">prim_structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_recp_symmetry_operation</span><span class="p">()</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">miller_list</span> <span class="o">=</span> <span class="n">conv_hkl_list</span>
        <span class="n">symm_ops</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">get_recp_symmetry_operation</span><span class="p">()</span>

    <span class="n">unique_millers</span><span class="p">,</span> <span class="n">unique_millers_conv</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>

    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">miller</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">miller_list</span><span class="p">):</span>
        <span class="n">d</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">reduce</span><span class="p">(</span><span class="n">gcd</span><span class="p">,</span> <span class="n">miller</span><span class="p">))</span>
        <span class="n">miller</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">i</span> <span class="o">/</span> <span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">miller</span><span class="p">])</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">is_already_analyzed</span><span class="p">(</span><span class="n">miller</span><span class="p">,</span> <span class="n">unique_millers</span><span class="p">,</span> <span class="n">symm_ops</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_crystal_system</span><span class="p">()</span> <span class="o">==</span> <span class="s2">&quot;trigonal&quot;</span><span class="p">:</span>
                <span class="c1"># Now we find the distinct primitive hkls using</span>
                <span class="c1"># the primitive symmetry operations and their</span>
                <span class="c1"># corresponding hkls in the conventional setting</span>
                <span class="n">unique_millers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">miller</span><span class="p">)</span>
                <span class="n">d</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">reduce</span><span class="p">(</span><span class="n">gcd</span><span class="p">,</span> <span class="n">conv_hkl_list</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
                <span class="n">cmiller</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">i</span> <span class="o">/</span> <span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">conv_hkl_list</span><span class="p">[</span><span class="n">i</span><span class="p">]])</span>
                <span class="n">unique_millers_conv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cmiller</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">unique_millers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">miller</span><span class="p">)</span>
                <span class="n">unique_millers_conv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">miller</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">return_hkil</span> <span class="ow">and</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_crystal_system</span><span class="p">()</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;trigonal&quot;</span><span class="p">,</span> <span class="s2">&quot;hexagonal&quot;</span><span class="p">]:</span>
        <span class="k">return</span> <span class="p">[(</span><span class="n">hkl</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">hkl</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">hkl</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">hkl</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
                 <span class="n">hkl</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">for</span> <span class="n">hkl</span> <span class="ow">in</span> <span class="n">unique_millers_conv</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">unique_millers_conv</span></div>


<div class="viewcode-block" id="hkl_transformation"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.hkl_transformation">[docs]</a><span class="k">def</span> <span class="nf">hkl_transformation</span><span class="p">(</span><span class="n">transf</span><span class="p">,</span> <span class="n">miller_index</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Returns the Miller index from setting</span>
<span class="sd">    A to B using a transformation matrix</span>
<span class="sd">    Args:</span>
<span class="sd">        transf (3x3 array): The transformation matrix</span>
<span class="sd">            that transforms a lattice of A to B</span>
<span class="sd">        miller_index ([h, k, l]): Miller index to transform to setting B</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c1"># Get a matrix of whole numbers (ints)</span>

    <span class="k">def</span> <span class="nf">lcm</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span> <span class="o">//</span> <span class="n">math</span><span class="o">.</span><span class="n">gcd</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>

    <span class="n">reduced_transf</span> <span class="o">=</span> <span class="n">reduce</span><span class="p">(</span><span class="n">lcm</span><span class="p">,</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="mi">1</span> <span class="o">/</span> <span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="o">*</span><span class="n">transf</span><span class="p">)</span> <span class="k">if</span> <span class="n">i</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">])</span> <span class="o">*</span> <span class="n">transf</span>
    <span class="n">reduced_transf</span> <span class="o">=</span> <span class="n">reduced_transf</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>

    <span class="c1"># perform the transformation</span>
    <span class="n">t_hkl</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">reduced_transf</span><span class="p">,</span> <span class="n">miller_index</span><span class="p">)</span>
    <span class="n">d</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">reduce</span><span class="p">(</span><span class="n">gcd</span><span class="p">,</span> <span class="n">t_hkl</span><span class="p">))</span>
    <span class="n">t_hkl</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">i</span> <span class="o">/</span> <span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">t_hkl</span><span class="p">])</span>

    <span class="c1"># get mostly positive oriented Miller index</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">t_hkl</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">])</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">t_hkl</span> <span class="o">*=</span> <span class="o">-</span><span class="mi">1</span>

    <span class="k">return</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">t_hkl</span><span class="p">)</span></div>


<div class="viewcode-block" id="generate_all_slabs"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.generate_all_slabs">[docs]</a><span class="k">def</span> <span class="nf">generate_all_slabs</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">max_index</span><span class="p">,</span> <span class="n">min_slab_size</span><span class="p">,</span> <span class="n">min_vacuum_size</span><span class="p">,</span>
                       <span class="n">bonds</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">ftol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">max_broken_bonds</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
                       <span class="n">lll_reduce</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">center_slab</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">primitive</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                       <span class="n">max_normal_search</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">symmetrize</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">repair</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                       <span class="n">include_reconstructions</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">in_unit_planes</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A function that finds all different slabs up to a certain miller index.</span>
<span class="sd">    Slabs oriented under certain Miller indices that are equivalent to other</span>
<span class="sd">    slabs in other Miller indices are filtered out using symmetry operations</span>
<span class="sd">    to get rid of any repetitive slabs. For example, under symmetry operations,</span>
<span class="sd">    CsCl has equivalent slabs in the (0,0,1), (0,1,0), and (1,0,0) direction.</span>

<span class="sd">    Args:</span>
<span class="sd">        structure (Structure): Initial input structure. Note that to</span>
<span class="sd">                ensure that the miller indices correspond to usual</span>
<span class="sd">                crystallographic definitions, you should supply a conventional</span>
<span class="sd">                unit cell structure.</span>
<span class="sd">        max_index (int): The maximum Miller index to go up to.</span>
<span class="sd">        min_slab_size (float): In Angstroms</span>
<span class="sd">        min_vacuum_size (float): In Angstroms</span>
<span class="sd">        bonds ({(specie1, specie2): max_bond_dist}: bonds are</span>
<span class="sd">            specified as a dict of tuples: float of specie1, specie2</span>
<span class="sd">            and the max bonding distance. For example, PO4 groups may be</span>
<span class="sd">            defined as {(&quot;P&quot;, &quot;O&quot;): 3}.</span>
<span class="sd">        tol (float): Threshold parameter in fcluster in order to check</span>
<span class="sd">            if two atoms are lying on the same plane. Default thresh set</span>
<span class="sd">            to 0.1 Angstrom in the direction of the surface normal.</span>
<span class="sd">        max_broken_bonds (int): Maximum number of allowable broken bonds</span>
<span class="sd">            for the slab. Use this to limit # of slabs (some structures</span>
<span class="sd">            may have a lot of slabs). Defaults to zero, which means no</span>
<span class="sd">            defined bonds must be broken.</span>
<span class="sd">        lll_reduce (bool): Whether to perform an LLL reduction on the</span>
<span class="sd">            eventual structure.</span>
<span class="sd">        center_slab (bool): Whether to center the slab in the cell with</span>
<span class="sd">            equal vacuum spacing from the top and bottom.</span>
<span class="sd">        primitive (bool): Whether to reduce any generated slabs to a</span>
<span class="sd">            primitive cell (this does **not** mean the slab is generated</span>
<span class="sd">            from a primitive cell, it simply means that after slab</span>
<span class="sd">            generation, we attempt to find shorter lattice vectors,</span>
<span class="sd">            which lead to less surface area and smaller cells).</span>
<span class="sd">        max_normal_search (int): If set to a positive integer, the code will</span>
<span class="sd">            conduct a search for a normal lattice vector that is as</span>
<span class="sd">            perpendicular to the surface as possible by considering</span>
<span class="sd">            multiples linear combinations of lattice vectors up to</span>
<span class="sd">            max_normal_search. This has no bearing on surface energies,</span>
<span class="sd">            but may be useful as a preliminary step to generating slabs</span>
<span class="sd">            for absorption and other sizes. It is typical that this will</span>
<span class="sd">            not be the smallest possible cell for simulation. Normality</span>
<span class="sd">            is not guaranteed, but the oriented cell will have the c</span>
<span class="sd">            vector as normal as possible (within the search range) to the</span>
<span class="sd">            surface. A value of up to the max absolute Miller index is</span>
<span class="sd">            usually sufficient.</span>
<span class="sd">        symmetrize (bool): Whether or not to ensure the surfaces of the</span>
<span class="sd">            slabs are equivalent.</span>
<span class="sd">        repair (bool): Whether to repair terminations with broken bonds</span>
<span class="sd">            or just omit them</span>
<span class="sd">        include_reconstructions (bool): Whether to include reconstructed</span>
<span class="sd">            slabs available in the reconstructions_archive.json file.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">all_slabs</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">for</span> <span class="n">miller</span> <span class="ow">in</span> <span class="n">get_symmetrically_distinct_miller_indices</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span>
                                                            <span class="n">max_index</span><span class="p">):</span>
        <span class="n">gen</span> <span class="o">=</span> <span class="n">SlabGenerator</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">miller</span><span class="p">,</span> <span class="n">min_slab_size</span><span class="p">,</span>
                            <span class="n">min_vacuum_size</span><span class="p">,</span> <span class="n">lll_reduce</span><span class="o">=</span><span class="n">lll_reduce</span><span class="p">,</span>
                            <span class="n">center_slab</span><span class="o">=</span><span class="n">center_slab</span><span class="p">,</span> <span class="n">primitive</span><span class="o">=</span><span class="n">primitive</span><span class="p">,</span>
                            <span class="n">max_normal_search</span><span class="o">=</span><span class="n">max_normal_search</span><span class="p">,</span>
                            <span class="n">in_unit_planes</span><span class="o">=</span><span class="n">in_unit_planes</span><span class="p">)</span>
        <span class="n">slabs</span> <span class="o">=</span> <span class="n">gen</span><span class="o">.</span><span class="n">get_slabs</span><span class="p">(</span><span class="n">bonds</span><span class="o">=</span><span class="n">bonds</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="n">tol</span><span class="p">,</span> <span class="n">ftol</span><span class="o">=</span><span class="n">ftol</span><span class="p">,</span> <span class="n">symmetrize</span><span class="o">=</span><span class="n">symmetrize</span><span class="p">,</span>
                              <span class="n">max_broken_bonds</span><span class="o">=</span><span class="n">max_broken_bonds</span><span class="p">,</span> <span class="n">repair</span><span class="o">=</span><span class="n">repair</span><span class="p">)</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">slabs</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> has </span><span class="si">%d</span><span class="s2"> slabs... &quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">miller</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">slabs</span><span class="p">)))</span>
            <span class="n">all_slabs</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">slabs</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">include_reconstructions</span><span class="p">:</span>
        <span class="n">sg</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
        <span class="n">symbol</span> <span class="o">=</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_space_group_symbol</span><span class="p">()</span>
        <span class="c1"># enumerate through all posisble reconstructions in the</span>
        <span class="c1"># archive available for this particular structure (spacegroup)</span>
        <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">instructions</span> <span class="ow">in</span> <span class="n">reconstructions_archive</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="k">if</span> <span class="s2">&quot;base_reconstruction&quot;</span> <span class="ow">in</span> <span class="n">instructions</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
                <span class="n">instructions</span> <span class="o">=</span> <span class="n">reconstructions_archive</span><span class="p">[</span><span class="n">instructions</span><span class="p">[</span><span class="s2">&quot;base_reconstruction&quot;</span><span class="p">]]</span>
            <span class="k">if</span> <span class="n">instructions</span><span class="p">[</span><span class="s2">&quot;spacegroup&quot;</span><span class="p">][</span><span class="s2">&quot;symbol&quot;</span><span class="p">]</span> <span class="o">==</span> <span class="n">symbol</span><span class="p">:</span>
                <span class="c1"># check if this reconstruction has a max index</span>
                <span class="c1"># equal or less than the given max index</span>
                <span class="k">if</span> <span class="nb">max</span><span class="p">(</span><span class="n">instructions</span><span class="p">[</span><span class="s2">&quot;miller_index&quot;</span><span class="p">])</span> <span class="o">&gt;</span> <span class="n">max_index</span><span class="p">:</span>
                    <span class="k">continue</span>
                <span class="n">recon</span> <span class="o">=</span> <span class="n">ReconstructionGenerator</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">min_slab_size</span><span class="p">,</span>
                                                <span class="n">min_vacuum_size</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
                <span class="n">all_slabs</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">recon</span><span class="o">.</span><span class="n">build_slabs</span><span class="p">())</span>

    <span class="k">return</span> <span class="n">all_slabs</span></div>


<div class="viewcode-block" id="get_slab_regions"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.get_slab_regions">[docs]</a><span class="k">def</span> <span class="nf">get_slab_regions</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">blength</span><span class="o">=</span><span class="mf">3.5</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Function to get the ranges of the slab regions. Useful for discerning where</span>
<span class="sd">    the slab ends and vacuum begins if the slab is not fully within the cell</span>
<span class="sd">    Args:</span>
<span class="sd">        slab (Structure): Structure object modelling the surface</span>
<span class="sd">        blength (float, Ang): The bondlength between atoms. You generally</span>
<span class="sd">            want this value to be larger than the actual bondlengths in</span>
<span class="sd">            order to find atoms that are part of the slab</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">fcoords</span><span class="p">,</span> <span class="n">indices</span><span class="p">,</span> <span class="n">all_indices</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[],</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">slab</span><span class="p">:</span>
        <span class="c1"># find sites with c &lt; 0 (noncontiguous)</span>
        <span class="n">neighbors</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">site</span><span class="p">,</span> <span class="n">blength</span><span class="p">,</span> <span class="n">include_index</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                                       <span class="n">include_image</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="c1"># sites are noncontiguous within cell</span>
                <span class="n">fcoords</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
                <span class="n">indices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nn</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span>
                <span class="k">if</span> <span class="n">nn</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">all_indices</span><span class="p">:</span>
                    <span class="n">all_indices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nn</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span>

    <span class="k">if</span> <span class="n">fcoords</span><span class="p">:</span>
        <span class="c1"># If slab is noncontiguous, locate the lowest</span>
        <span class="c1"># site within the upper region of the slab</span>
        <span class="k">while</span> <span class="n">fcoords</span><span class="p">:</span>
            <span class="n">last_fcoords</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">fcoords</span><span class="p">)</span>
            <span class="n">last_indices</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">indices</span><span class="p">)</span>
            <span class="n">site</span> <span class="o">=</span> <span class="n">slab</span><span class="p">[</span><span class="n">indices</span><span class="p">[</span><span class="n">fcoords</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">fcoords</span><span class="p">))]]</span>
            <span class="n">neighbors</span> <span class="o">=</span> <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">site</span><span class="p">,</span> <span class="n">blength</span><span class="p">,</span> <span class="n">include_index</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                                           <span class="n">include_image</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
            <span class="n">fcoords</span><span class="p">,</span> <span class="n">indices</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>
            <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">:</span>
                <span class="k">if</span> <span class="mi">1</span> <span class="o">&gt;</span> <span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> \
                        <span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span>
                    <span class="c1"># sites are noncontiguous within cell</span>
                    <span class="n">fcoords</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nn</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
                    <span class="n">indices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nn</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span>
                    <span class="k">if</span> <span class="n">nn</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">all_indices</span><span class="p">:</span>
                        <span class="n">all_indices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nn</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span>

        <span class="c1"># Now locate the highest site within the lower region of the slab</span>
        <span class="n">upper_fcoords</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">slab</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">all</span><span class="p">([</span><span class="n">nn</span><span class="o">.</span><span class="n">index</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">all_indices</span> <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span>
                    <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">site</span><span class="p">,</span> <span class="n">blength</span><span class="p">)]):</span>
                <span class="n">upper_fcoords</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
        <span class="n">coords</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">last_fcoords</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">fcoords</span> <span class="k">else</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">fcoords</span><span class="p">)</span>
        <span class="n">min_top</span> <span class="o">=</span> <span class="n">slab</span><span class="p">[</span><span class="n">last_indices</span><span class="p">[</span><span class="n">coords</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">coords</span><span class="p">))]]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
        <span class="n">ranges</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="n">upper_fcoords</span><span class="p">)],</span> <span class="p">[</span><span class="n">min_top</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># If the entire slab region is within the slab cell, just</span>
        <span class="c1"># set the range as the highest and lowest site in the slab</span>
        <span class="n">sorted_sites</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">slab</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">site</span><span class="p">:</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
        <span class="n">ranges</span> <span class="o">=</span> <span class="p">[[</span><span class="n">sorted_sites</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span>
                   <span class="n">sorted_sites</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span>

    <span class="k">return</span> <span class="n">ranges</span></div>


<div class="viewcode-block" id="miller_index_from_sites"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.miller_index_from_sites">[docs]</a><span class="k">def</span> <span class="nf">miller_index_from_sites</span><span class="p">(</span><span class="n">lattice</span><span class="p">,</span> <span class="n">coords</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                            <span class="n">round_dp</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Get the Miller index of a plane from a list of site coordinates.</span>

<span class="sd">    A minimum of 3 sets of coordinates are required. If more than 3 sets of</span>
<span class="sd">    coordinates are given, the best plane that minimises the distance to all</span>
<span class="sd">    points will be calculated.</span>

<span class="sd">    Args:</span>
<span class="sd">        lattice (list or Lattice): A 3x3 lattice matrix or `Lattice` object (for</span>
<span class="sd">            example obtained from Structure.lattice).</span>
<span class="sd">        coords (iterable): A list or numpy array of coordinates. Can be</span>
<span class="sd">            cartesian or fractional coordinates. If more than three sets of</span>
<span class="sd">            coordinates are provided, the best plane that minimises the</span>
<span class="sd">            distance to all sites will be calculated.</span>
<span class="sd">        coords_are_cartesian (bool, optional): Whether the coordinates are</span>
<span class="sd">            in cartesian space. If using fractional coordinates set to False.</span>
<span class="sd">        round_dp (int, optional): The number of decimal places to round the</span>
<span class="sd">            miller index to.</span>
<span class="sd">        verbose (bool, optional): Whether to print warnings.</span>

<span class="sd">    Returns:</span>
<span class="sd">        (tuple): The Miller index.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">lattice</span><span class="p">,</span> <span class="n">Lattice</span><span class="p">):</span>
        <span class="n">lattice</span> <span class="o">=</span> <span class="n">Lattice</span><span class="p">(</span><span class="n">lattice</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">lattice</span><span class="o">.</span><span class="n">get_miller_index_from_coords</span><span class="p">(</span>
        <span class="n">coords</span><span class="p">,</span> <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="n">coords_are_cartesian</span><span class="p">,</span> <span class="n">round_dp</span><span class="o">=</span><span class="n">round_dp</span><span class="p">,</span>
        <span class="n">verbose</span><span class="o">=</span><span class="n">verbose</span><span class="p">)</span></div>


<div class="viewcode-block" id="center_slab"><a class="viewcode-back" href="../../../pymatgen.core.surface.html#pymatgen.core.surface.center_slab">[docs]</a><span class="k">def</span> <span class="nf">center_slab</span><span class="p">(</span><span class="n">slab</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    The goal here is to ensure the center of the slab region</span>
<span class="sd">        is centered close to c=0.5. This makes it easier to</span>
<span class="sd">        find the surface sites and apply operations like doping.</span>

<span class="sd">    There are three cases where the slab in not centered:</span>

<span class="sd">    1. The slab region is completely between two vacuums in the</span>
<span class="sd">    box but not necessarily centered. We simply shift the</span>
<span class="sd">    slab by the difference in its center of mass and 0.5</span>
<span class="sd">    along the c direction.</span>

<span class="sd">    2. The slab completely spills outside the box from the bottom</span>
<span class="sd">    and into the top. This makes it incredibly difficult to</span>
<span class="sd">    locate surface sites. We iterate through all sites that</span>
<span class="sd">    spill over (z&gt;c) and shift all sites such that this specific</span>
<span class="sd">    site is now on the other side. Repeat for all sites with z&gt;c.</span>

<span class="sd">    3. This is a simpler case of scenario 2. Either the top or bottom</span>
<span class="sd">    slab sites are at c=0 or c=1. Treat as scenario 2.</span>

<span class="sd">    Args:</span>
<span class="sd">        slab (Slab): Slab structure to center</span>
<span class="sd">    Returns:</span>
<span class="sd">        Returns a centered slab structure</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c1"># get a reasonable r cutoff to sample neighbors</span>
    <span class="n">bdists</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">([</span><span class="n">nn</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">nn</span> <span class="ow">in</span>
                     <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">slab</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">10</span><span class="p">)</span> <span class="k">if</span> <span class="n">nn</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">])</span>
    <span class="n">r</span> <span class="o">=</span> <span class="n">bdists</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">3</span>

    <span class="n">all_indices</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">slab</span><span class="p">)]</span>

    <span class="c1"># check if structure is case 2 or 3, shift all the</span>
    <span class="c1"># sites up to the other side until it is case 1</span>
    <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">slab</span><span class="p">:</span>
        <span class="k">if</span> <span class="nb">any</span><span class="p">([</span><span class="n">nn</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">slab</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">c</span> <span class="k">for</span> <span class="n">nn</span>
                <span class="ow">in</span> <span class="n">slab</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span><span class="n">site</span><span class="p">,</span> <span class="n">r</span><span class="p">)]):</span>
            <span class="n">shift</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">site</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.05</span>
            <span class="n">slab</span><span class="o">.</span><span class="n">translate_sites</span><span class="p">(</span><span class="n">all_indices</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">shift</span><span class="p">])</span>

    <span class="c1"># now the slab is case 1, shift the center of mass of the slab to 0.5</span>
    <span class="n">weights</span> <span class="o">=</span> <span class="p">[</span><span class="n">s</span><span class="o">.</span><span class="n">species</span><span class="o">.</span><span class="n">weight</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">slab</span><span class="p">]</span>
    <span class="n">center_of_mass</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">average</span><span class="p">(</span><span class="n">slab</span><span class="o">.</span><span class="n">frac_coords</span><span class="p">,</span>
                                <span class="n">weights</span><span class="o">=</span><span class="n">weights</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">shift</span> <span class="o">=</span> <span class="mf">0.5</span> <span class="o">-</span> <span class="n">center_of_mass</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
    <span class="n">slab</span><span class="o">.</span><span class="n">translate_sites</span><span class="p">(</span><span class="n">all_indices</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">shift</span><span class="p">])</span>

    <span class="k">return</span> <span class="n">slab</span></div>


<span class="k">def</span> <span class="nf">_reduce_vector</span><span class="p">(</span><span class="n">vector</span><span class="p">):</span>
    <span class="c1"># small function to reduce vectors</span>

    <span class="n">d</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">reduce</span><span class="p">(</span><span class="n">gcd</span><span class="p">,</span> <span class="n">vector</span><span class="p">))</span>
    <span class="n">vector</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">i</span> <span class="o">/</span> <span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">vector</span><span class="p">])</span>

    <span class="k">return</span> <span class="n">vector</span>
</pre></div>

            <div class="clearer"></div>
          </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../../index.html">pymatgen 2020.7.3 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="../../pymatgen.html" >pymatgen</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">pymatgen.core.surface</a></li> 
      </ul>
    </div>

    <div class="footer" role="contentinfo">
        &#169; Copyright 2011, Pymatgen Development Team.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.2.
    </div>
<div class="footer">This page uses <a href="http://analytics.google.com/">
Google Analytics</a> to collect statistics. You can disable it by blocking
the JavaScript coming from www.google-analytics.com.
<script type="text/javascript">
  (function() {
    var ga = document.createElement('script');
    ga.src = ('https:' == document.location.protocol ?
              'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    ga.setAttribute('async', 'true');
    document.documentElement.firstChild.appendChild(ga);
  })();
</script>
</div>

  </body>
</html>